<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"><title>二十二、Gradle Java 插件 | 云少IT</title><meta name="keywords" content="云少IT,IT,技术,分享,程序员,博客,教程,工具,框架,bug,java,spring,数据库,"><meta name="author" content="云少"><meta name="copyright" content="云少"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="mobile-web-app-capable" content="yes"><meta name="apple-touch-fullscreen" content="yes"><meta name="apple-mobile-web-app-title" content="二十二、Gradle Java 插件"><meta name="application-name" content="二十二、Gradle Java 插件"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="#ffffff"><meta property="og:type" content="article"><meta property="og:title" content="二十二、Gradle Java 插件"><meta property="og:url" content="https://it985.github.io/posts/e35ffad1.html"><meta property="og:site_name" content="云少IT"><meta property="og:description" content="二十二、Gradle Java 插件Java 插件向一个项目添加了 Java 编译、 测试和 bundling 的能力。它是很多其他 Gradle 插件的基础服务。 用法要使用 Java 插件，请在构建脚本中加入： 使用 Java 插件 build.gradle 1apply plugin: &amp;amp;#x"><meta property="og:locale" content="zh-CN"><meta property="og:image" content="https://www.bing.com/th?id=OHR.AmazonMangroves_EN-US7068770726_UHD.jpg"><meta property="article:author" content="云少"><meta property="article:tag" content="云少IT,IT,技术,分享,程序员,博客,教程,工具,框架,bug,java,spring,数据库,"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://www.bing.com/th?id=OHR.AmazonMangroves_EN-US7068770726_UHD.jpg"><meta name="description" content="二十二、Gradle Java 插件Java 插件向一个项目添加了 Java 编译、 测试和 bundling 的能力。它是很多其他 Gradle 插件的基础服务。 用法要使用 Java 插件，请在构建脚本中加入： 使用 Java 插件 build.gradle 1apply plugin: &amp;amp;#x"><link rel="shortcut icon" href="/img/logo.webp"><link rel="canonical" href="https://it985.github.io/posts/e35ffad1"><link rel="preconnect" href="//npm.elemecdn.com"><link rel="preconnect" href="//npm.onmicrosoft.cn"><link rel="preconnect" href="//www.google-analytics.com" crossorigin=""><link rel="preconnect" href="//busuanzi.ibruce.info"><meta name="google-site-verification" content="NuBZ4r-QCqSgo4XUScdEsQW0bolIHEiVGq4A16ndPQA"><meta name="baidu-site-verification" content="code-xxx"><meta name="msvalidate.01" content="xxx"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.cbd.int/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://cdn.cbd.int/node-snackbar@0.1.16/dist/snackbar.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://cdn.cbd.int/@fancyapps/ui@5.0.20/dist/fancybox/fancybox.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.0/swiper/swiper.min.css" media="print" onload='this.media="all"'><script async src="https://www.googletagmanager.com/gtag/js?id=G-3VMKW5TZBM"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-3VMKW5TZBM")</script><script>const GLOBAL_CONFIG={linkPageTop:{enable:!0,title:"与数百名博主无限进步",addFriendPlaceholder:"昵称（请勿包含博客等字样）：\n网站地址（要求博客地址，请勿提交个人主页）：\n头像图片url（请提供尽可能清晰的图片，我会上传到我自己的图床）：\n描述：\n站点截图（可选）：\n"},peoplecanvas:void 0,postHeadAiDescription:{enable:!0,gptName:"云AI",mode:"tianli",switchBtn:!1,btnLink:"https://afdian.net/item/886a79d4db6711eda42a52540025c377",randomNum:3,basicWordCount:1e3,key:"48580d1e3f53ae174a1e",Referer:"https://blog.tryrun.top"},diytitle:{enable:!0,leaveTitle:"w(ﾟДﾟ)w 不要走！再看看嘛！",backTitle:"♪(^∇^*)欢迎肥来！"},LA51:{enable:!0,ck:"JiFOrFoQklEn9YLS",LingQueMonitorID:"JiqlTmdeI4e1fPbd"},greetingBox:{enable:!0,default:"晚上好👋",list:[{greeting:"晚安😴",startTime:0,endTime:5},{greeting:"早上好鸭👋, 祝你一天好心情！",startTime:6,endTime:9},{greeting:"上午好👋, 状态很好，鼓励一下～",startTime:10,endTime:10},{greeting:"11点多啦, 在坚持一下就吃饭啦～",startTime:11,endTime:11},{greeting:"午安👋, 宝贝",startTime:12,endTime:14},{greeting:"🌈充实的一天辛苦啦！",startTime:14,endTime:18},{greeting:"19点喽, 奖励一顿丰盛的大餐吧🍔。",startTime:19,endTime:19},{greeting:"晚上好👋, 在属于自己的时间好好放松😌~",startTime:20,endTime:24}]},twikooEnvId:"https://twikoo.tryrun.top/",commentBarrageConfig:void 0,root:"/",preloader:{source:2},friends_vue_info:{apiurl:"https://friends.tryrun.top/"},navMusic:!1,mainTone:void 0,authorStatus:{skills:["🤖️ 数码科技爱好者","🔍 分享与热心帮助","🏠 智能家居小能手","🔨 设计开发一条龙","🤝 专修交互与设计","🏃 脚踏实地行动派","🧱 团队小组发动机","💢 壮汉人狠话不多"]},algolia:{appId:"T5VW6VDYLS",apiKey:"227bcb041816af13cb1698db15a8ac89",indexName:"hexo-blog",hits:{per_page:6},languages:{input_placeholder:"输入关键词后按下回车查找",hits_empty:"找不到您查询的内容：${query}",hits_stats:"找到 ${hits} 条结果，用时 ${time} 毫秒"}},localSearch:void 0,translate:{defaultEncoding:2,translateDelay:0,msgToTraditionalChinese:"繁",msgToSimplifiedChinese:"简",rightMenuMsgToTraditionalChinese:"转为繁体",rightMenuMsgToSimplifiedChinese:"转为简体"},noticeOutdate:{limitDay:365,position:"top",messagePrev:"It has been",messageNext:"days since the last update, the content of the article may be outdated."},highlight:{plugin:"highlighjs",highlightCopy:!0,highlightLang:!0,highlightHeightLimit:330},copy:{success:"复制成功",error:"复制错误",noSupport:"浏览器不支持"},relativeDate:{homepage:!0,simplehomepage:!1,post:!0},runtime:"天",date_suffix:{just:"刚刚",min:"分钟前",hour:"小时前",day:"天前",month:"个月前"},copyright:void 0,lightbox:"fancybox",Snackbar:{chs_to_cht:"你已切换为繁体",cht_to_chs:"你已切换为简体",day_to_night:"你已切换为深色模式",night_to_day:"你已切换为浅色模式",bgLight:"#425AEF",bgDark:"#1f1f1f",position:"top-center"},source:{justifiedGallery:{js:"https://cdn.cbd.int/flickr-justified-gallery@2.1.2/dist/fjGallery.min.js",css:"https://cdn.cbd.int/flickr-justified-gallery@2.1.2/dist/fjGallery.css"}},isPhotoFigcaption:!1,islazyload:!0,isAnchor:!1,shortcutKey:void 0,autoDarkmode:!0}</script><script id="config-diff">var GLOBAL_CONFIG_SITE={configTitle:"云少IT",title:"二十二、Gradle Java 插件",postAI:"true",pageFillDescription:"二十二、Gradle Java 插件, 用法, 源集, 任务, 项目布局, 更改项目布局, 依赖管理, 常规属性, 使用源集, 源集属性, 定义新的源集, 一些源集的范例, Javadoc, 清理, 资源, CompileJava, Test, 测试执行, 调试, 测试过滤, 通过系统属性执行单一的测试, 测试检测, 测试分组, 测试报告, TestNG 参数化方法和报告, 常规值, Jar, Manifest二十二插件插件向一个项目添加了编译测试和的能力它是很多其他插件的基础服务用法要使用插件请在构建脚本中加入使用插件源集插件引入了一个源集的概念一个源集只是一组用于编译并一起执行的源文件这些源文件可能包括源代码文件和资源文件其他有一些插件添加了在源集里包含和的源代码文件的能力一个源集有一个相关联的编译类路径和运行时类路径源集的一个用途是把源文件进行逻辑上的分组以描述它们的目的例如你可能会使用一个源集来定义一个集成测试套件或者你可能会使用单独的源集来定义你的项目的和实现类插件定义了两个标准的源集分别是和源集包含你产品的源代码它们将被编译并组装成一个文件源集包含你的单元测试的源代码它们将被编译并使用或来执行任务插件向你的项目添加了大量的任务如下所示表插件任务任务名称依赖于类型描述产生编译类路径中的所有任务这包括了用于任务使用编译产品中的源文件把生产资源文件拷贝到生产的类目录中一些插件添加了额外的编译任务组装生产的类目录再加上所有能产生测试编译类路径的任务使用编译的测试源文件把测试的资源文件拷贝到测试的类目录中一些插件添加了额外的测试编译任务组装测试的类目录组装文件使用生成生产的源代码的文档再加上所有产生测试运行时类路径的任务使用或运行单元测试使用使用配置上传包括文件的构件删除项目的目录删除由指定的任务所产生的输出文件例如任务中所创建的文件任务所创建的测试结果对于每个你添加到该项目中的源集插件将添加以下的编译任务表插件源集任务任务名称依赖于类型描述所有产生源集编译类路径的任务使用编译给定的源集中的源文件把给定的源集的资源文件拷贝到类目录中某些插件还为源集添加了额外的编译任务组装给定源集的类目录插件还增加了大量的任务构成该项目的生命周期表插件生命周期任务任务名称依赖于类型描述项目中的所有归档项目包括任务某些插件还向项目添加额外的归档任务组装项目中所有的归类文件项目中的所有核查项目包括任务某些插件还向项目添加额外的核查任务执行项目中所有的核查任务执行项目的完事构建任务执行项目本身及它所依赖的其他所有项目的完整构建任务执行项目本身及依赖它的其他所有项目的完整构建使用配置生成构件的任务组装指定配置的构件该任务由插件添加并由插件隐式实现使用配置上传构件的任务组装并上传指定配置的构件该任务由插件添加并由插件隐式实现使用配置上传构件的任务组装并上传指定配置的构件该任务由插件添加并由插件隐式实现项目布局插件会假定如下所示的项目布局这些目录都不需要一定存在或者是里面有什么内容插件将会进行编译不管它发现什么并处理缺少的任何东西表插件默认项目布局目录意义产品的源代码产品的资源测试源代码测试资源给定的源集的源代码给定的源集的资源更改项目布局你可以通过配置适当的源集来配置项目的布局这一点将在以下各节中详细讨论这里是如何更改和资源源目录的一个简短的例子自定义源代码布局依赖管理插件向项目添加了许多依赖配置如下图所示它对一些任务指定了这些配置如和表插件依赖配置名称继承自在哪些任务中使用意义编译时依赖运行时依赖用于编译测试的其他依赖只用于运行测试的其他依赖由本项目生产的构件如包本项目上的默认项目依赖配置包含本项目运行时所需要的构件和依赖对于每个你添加到项目中的源集插件都会添加以下的依赖配置表插件源集依赖配置名称继承自在哪些任务中使用意义给定源集的编译时依赖给定源集的运行时依赖常规属性插件向项目添加了许多常规属性如下图所示您可以在构建脚本中使用这些属性就像它们是对象的属性一样表插件目录属性属性名称类型默认值描述相对于目录的目录名称报告将生成到此目录报告将生成到此目录相对于目录的目录名称测试报告的文件将生成到此目录测试报告的文件将生成到此目录相对于目录的目录名称测试报告将生成到此目录测试报告生成到此目录相对于目录的目录名称类库将生成到此目录中类库将生成到此目录中相对于目录的目录名称发布的文件将生成到此目录中要发布的文件将生成到此目录相对于目录的目录名称文档将生成到此目录要生成文档的目录相对于目录的目录名称该目录用于缓存源代码的依赖信息该目录用于缓存源代码的依赖信息表插件其他属性属性名称类型默认值描述非空包含项目的源集可以使用字符串或数字来设置例如当前所使用的值当编译源代码时所使用的版本兼容性可以使用字符串或数字来设置例如要生成的类的版本像或文件这样的构件的一个空的清单要包括的所有文件的清单这些属性由和这些类型的常规对象提供使用源集你可以使用属性访问项目的源集这是项目的源集的容器它的类型是除此之后还有一个的脚本块可以传入一个闭包来配置源集容器源集容器的使用方式几乎与其他容器一样例如访问源集要配置一个现有的源集你只需使用上面的其中一种访问方法来设置源集的属性这些属性将在下文中进行介绍下面是一个配置的和资源目录的例子配置源集的源代码目录源集属性下表列出了一些重要的源集属性你可以在的文档中查看更多的详细信息表插件源集属性属性名称类型默认值描述非空用来确定一个源集的源集名称非空源集的输出文件包含它编译过的类和资源要生成的该源集的类的目录要生成的该源集的资源的目录配置该类路径在编译该源集的源文件时使用配置该类路径在执行该源集的类时使用非空该源集的源文件仅包含源文件目录里的文件并排除其他所有文件该源目录包含了此源集的所有源文件非空此源集的资源文件仅包含资源文件并且排除在资源源目录中找到的所有文件其他插件如插件会从该集合中排除其他类型的文件该源目录包含了此源集的资源文件该源集的所有文件有些插件如插件会从该集合中增加其他的源文件该源集的所有源文件包含所有的资源文件和源文件有些插件如插件会从该集合中增加其他的源文件定义新的源集要定义一个新的源集你只需在块中引用它下面是一个示例定义一个源集当您定义一个新的源集时插件会为该源集添加一些依赖配置如表插件源集依赖项配置所示你可以使用这些配置来定义源集的编译和运行时的依赖定义源集依赖插件还添加了大量的任务用于组装源集的类如表插件源设置任务所示例如对于一个被叫做的源集你可以运行来编译测试类编译源集的输出结果一些源集的范例添加一个包含了源集的类的包示例为一个源集装配一个文件为一个源集生成示例为一个源集生成添加一个测试套件以运行一个源集里的测试示例运行源集里的测试任务是的一个实例它支持核心的参数选项以及在可执行文件的参考文档中描述的标准参数选项对于支持的参数选项的完整列表请参考下面的类的文档和表插件属性任务属性类型默认值的名称和版本清理任务是的一个实例它只是删除由其属性表示的目录表插件性能任务属性类型默认值资源插件使用任务进行资源的处理它为该里的每个源集添加一个实例表插件属性任务属性类型默认值章节查找文件中所讲到的任何一种方式来设置插件为该里的每个源集添加一个实例一些最常见的配置选项如下所示表插件属性任务属性类型默认值任务委派了的任务将设置为将绕过任务而激活的直接编译器集成在未来的版本中将把它作为默认设置默认情况下编译器在过程中运行将设置为将会使编译出现在一个单独的进程中在任务中这意味着将会为每一个任务一个新的进程而这将会使编译变慢相反的直接编译器集成见上文将尽可能多地重用相同的编译器进程在这两种情况下使用指定的所有选项都将得到重视任务是的一个实例它会自动检测和执行源集中的所有单元测试测试执行完成后它还会生成一份报告同时支持和可以看一看的完整的测试执行测试在单独的中执行与构建进程隔离任务的可以让你控制什么时候开始有大量的属性用于控制测试进程的启动这包括系统属性参数和使用的可执行文件你可以指定是否要并行运行你的测试通过同时运行多个测试进程来提供并行测试的执行每个测试进程会依次执行一个单一的测试所以你一般不需要对你的测试做任何的配置来利用这一点属性指定在给定的时间可以运行的测试进程的最大数它的默认值是也就是说不并行执行测试测试进程程会为其将系统属性设置为一个唯一标识符这个标识符可以用于文件名称或其他资源标识符你可以指定在执行了一定数量的测试类之后重启那个测试进程这是一个很有用的替代方案让你的测试进程可以有很大的堆内存属性指定了要在测试进程中执行的测试类的最大数默认是每个测试进程中执行的测试数量不限该任务有一个属性用以控制测试失败时的行为会始终执行它检测到的每一个测试如果为并且有测试不通过那它会停止继续构建的默认值为属性可以配置哪些测试事件需要记录并且使用什么样的日志级别默认情况下对于每个失败的测试都只会打印一个简洁的消息请参阅查看如何把你的测试日志打印调整为你的偏好设置调试任务提供了一个属性可以设置为启动使在执行测试之前等待一个连接到它的端口上这也可以在调用时通过选项进行启用测试过滤从开始可以根据测试的名称模式只包含指定的测试过滤相对于测试类的包含或排除是一个不同的机制它将在接下来的段落中进行描述和后者基于文件比如测试实现类的物理位置的测试选择不支持的很多有趣的情况都可以用过滤来做到以下这些场景中有一些现在就可以处理而有一些则将在未来得到实现在指定的测试的方法级别上进行过滤执行单个测试方法基于自定义注解以后实现进行过滤基于测试层次结构进行过滤执行所有继承了某一基类以后实现的测试基于一些自定义的运行时的规则进行过滤例如某个系统属性或一些静态的特定值以后实现测试过滤功能具有以下的特征支持完整的限定类名称或完整的限定的方法名称例如通配符支付匹配任何字符提供了的命令行选项以方便地设置测试过滤器这对单一测试方法的执行的经典用例特别有用当使用该命令行选项选项时在构建脚本中声明的列入过滤器的测试将会被忽略尽最大努力对有着特定的测试框架的局限的测试进行过滤一些高级的综合的测试可能不完全符合过滤条件然而绝大多数的测试和用例都会被很好地处理测试过滤将会取代基于文件的测试选择后者可能在将来会被完全地取代掉我们将会继续改进测试过滤的并添加更多种类的过滤器在构建脚本中过滤测试有关更多的详细信息和示例请参阅的文档使用命令行选项的一些示例通过系统属性执行单一的测试这种机制已经被上述的测试过滤所取代设置一个的系统属性将会只执行匹配的那些测试这个可以是一个完整的多项目路径比如或者仅是一个任务名称将用于形成一个的包含模式如果这个模式无法找到任何测试那么将会抛出一个异常这是为了使你不会误以为测试通过如果执行了一个以上的子项目的测试该模式会被应用于每一个子项目中如果在一个特定的子项目中找不到测试用例那么将会抛出异常在这种情况下你可以使用路径标记法的模式这样该模式就会只应用于特定的子项目的测试任务中或者你可以指定要执行的任务的完整限定名称你还可以指定多个模式示例测试检测任务通过检查编译过的测试类来检测哪些类是测试类默认情况下它会扫描所有的文件您可以设置自定义的或这样就只有这些类才会被扫描根据所使用的测试框架或会使用不同的标准进行测试类的检测当使用时我们扫描和的测试类如果满足以下的任何一个条件这个类就被认为是一个测试类类或超类继承自或类或超类使用了进行注解类或超类含有一个带注解的方法当使用时我们扫描所有带有注解的方法请注意抽象类不会被执行还将扫描测试类路径中的文件里的继承树如果你不想要使用测试类检测可以通过设置为来禁用它这将使任务只使用来找到测试类如果为并且没有指定或模式则使用各自的默认值对于的默认值是而对于它的默认值是测试分组和可以对测试方法进行复杂的分组为对测试类和方法进行分组引入了类别的概念任务可以实现一个规范让你和想要的类别类别框架有一个非常相似的概念在中你可以指定不同的测试组应从测试执行中或的测试组可以在任务中配置对测试分组测试报告任务默认情况下会生成以下结果一个测试报告与任务兼容的格式的结果这种格式可以被许多工具所支持比如服务器有效二进制格式的结果这个任务会从这些二进制结果生成其他的结果您可以使用方法来禁用测试报告目前不能禁用其他的结果这里还有一个独立的任务类型它可以从一个或多个任务实例生成的二进制结果中生成测试报告要使用这个任务类型你需要定义一个和要包含到报告的测试结果这里是一个范例从子项目的单元测试中生成一个联合报告为多个子项目创建一个单元测试报告你应该注意到类型组合了多个测试任务的结果并且需要聚合各个测试类的结果这意味着如果一个给定的测试类被多个任务所执行那么测试报告将包括那个类的所有执行结果但它难以区分那个类的每次执行和它们的输出参数化方法和报告支持参数化测试方法允许一个特定的测试方法使用不同的输入执行多次会在这个方法的执行报告中包含进它的参数值给定一个带有两个参数名为参数化测试方法它将使用名称这个名称进行报告这使得在特定的迭代过程很容易确定参数值常规值表插件属性任务属性类型默认值任务创建一个包含类文件和项目资源的文件文件在依赖配置中被声明为一个构件这意味着这个文件被包含在一个依赖它的项目的类路径中如果你把你的项目上传到仓库这个文件会被声明为依赖描述符的一部分你可以在第节创建档案和第章发布中了解如何使用和配置每个或对象都有一个单独的实例的属性当生成时相应的文件也会被写入进去自定义的您可以创建一个单独的实例它可以用于共享两个包的信息创建一个对象你可以把其他的合并到任何一个对象中其他的可能使用文件路径来描述像上面的例子使用对另一个对象的引用指定的单独会根据在语句中所声明的顺序进行合并如果基本的和要合并的都定义了同一个的值那么默认情况下会采用要合并的的值你可以通过添加来完全自定义合并行为它可以让你对每一项生成的访问它的一个实例这个合并操作不会在语句中就马上被触发它是懒执行的不管是对于生成一个包还是调用了或者你可以很轻松地把一个写入磁盘中指定的单独",isPost:!0,isHome:!1,isHighlightShrink:!0,isToc:!0,postUpdate:"2020-03-22 22:29:54",postMainColor:""}</script><noscript><style>#nav{opacity:1}.justified-gallery img{opacity:1}#post-meta time,#recent-posts time{display:inline!important}</style></noscript><script>(e=>{e.saveToLocal={set:(e,t,a)=>{var o;0!==a&&(o=Date.now(),localStorage.setItem(e,JSON.stringify({value:t,expiry:o+864e5*a})))},get:e=>{var t=localStorage.getItem(e);if(t){t=JSON.parse(t);if(!(Date.now()>t.expiry))return t.value;localStorage.removeItem(e)}}},e.getScript=(o,c={})=>new Promise((t,e)=>{const a=document.createElement("script");a.src=o,a.async=!0,a.onerror=e,a.onload=a.onreadystatechange=function(){var e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,t())},Object.keys(c).forEach(e=>{a.setAttribute(e,c[e])}),document.head.appendChild(a)}),e.getCSS=(o,c=!1)=>new Promise((t,e)=>{const a=document.createElement("link");a.rel="stylesheet",a.href=o,c&&(a.id=c),a.onerror=e,a.onload=a.onreadystatechange=function(){var e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,t())},document.head.appendChild(a)}),e.activateDarkMode=()=>{document.documentElement.setAttribute("data-theme","dark"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#0d0d0d")},e.activateLightMode=()=>{document.documentElement.setAttribute("data-theme","light"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#ffffff")};var e=saveToLocal.get("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches,a=window.matchMedia("(prefers-color-scheme: light)").matches,o=window.matchMedia("(prefers-color-scheme: no-preference)").matches,c=!t&&!a&&!o,t=(void 0===e?(a?activateLightMode():t?activateDarkMode():(o||c)&&((a=(new Date).getHours())<=6||18<=a?activateDarkMode:activateLightMode)(),window.matchMedia("(prefers-color-scheme: dark)").addListener(e=>{void 0===saveToLocal.get("theme")&&(e.matches?activateDarkMode:activateLightMode)()})):("light"===e?activateLightMode:activateDarkMode)(),saveToLocal.get("aside-status"));void 0!==t&&("hide"===t?document.documentElement.classList.add("hide-aside"):document.documentElement.classList.remove("hide-aside"));/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)&&document.documentElement.classList.add("apple")})(window)</script><link rel="stylesheet" href="/css/1.min.css?1" media="async" onload='this.media="all"'><link rel="stylesheet" href="/css/bg.css?1" media="async" onload='this.media="all"'><meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="云少IT" type="application/atom+xml"><link rel="alternate" href="/rss.xml" title="云少IT" type="application/rss+xml"></head><body data-type="anzhiyu"><div id="web_bg"></div><div id="an_music_bg"></div><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.1.10/progress_bar/progress_bar.css"><script async src="https://cdn.cbd.int/pace-js@1.2.4/pace.min.js" data-pace-options="{ &quot;restartOnRequestAfter&quot;:false,&quot;eventLag&quot;:false}"></script><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav id="nav"><div id="nav-group"><span id="blog_name"><div class="back-home-button"><i class="anzhiyufont anzhiyu-icon-grip-vertical"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">网页</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top/" title="博客"><img class="back-menu-item-icon" src="/img/favicon.ico" alt="博客"><span class="back-menu-item-text">博客</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="图床"><img class="back-menu-item-icon" src="https://www.tryrun.top/favicon.ico" alt="图床"><span class="back-menu-item-text">图床</span></a></div></div></div></div><a id="site-name" href="/" accesskey="h"><div class="title">云少IT</div><i class="anzhiyufont anzhiyu-icon-house-chimney"></i></a></span><div class="mask-name-container"><div id="name-container"><a id="page-name" href="javascript:anzhiyu.scrollToDest(0, 500)" rel="external nofollow noreferrer">PAGE_NAME</a></div></div><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>望四方</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="anzhiyufont anzhiyu-icon-box-archive faa-tada" style="font-size:.9em"></i><span> 归名档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="anzhiyufont anzhiyu-icon-shapes faa-tada" style="font-size:.9em"></i><span> 归四类</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags faa-tada" style="font-size:.9em"></i><span> 书中签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/charts/"><i class="fa-fw fas fa-chart-bar faa-tada"></i><span> 统计</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="anzhiyufont anzhiyu-icon-link faa-tada" style="font-size:.9em"></i><span> 四方好友</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="anzhiyufont anzhiyu-icon-artstation faa-tada" style="font-size:.9em"></i><span> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><i class="anzhiyufont anzhiyu-icon-envelope faa-tada" style="font-size:.9em"></i><span> 留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/"><i class="anzhiyufont anzhiyu-icon-bilibili faa-tada" style="font-size:.9em"></i><span> 追番页</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/album/"><i class="anzhiyufont anzhiyu-icon-images faa-tada" style="font-size:.9em"></i><span> 刹那间</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/equipment/"><i class="fas fa-heart faa-tada"></i><span> 我的装备</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/collect/"><i class="fas fa-camcorder faa-tada"></i><span> 观影阁</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="anzhiyufont anzhiyu-icon-paper-plane faa-tada" style="font-size:.9em"></i><span> 关于本人</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="anzhiyufont anzhiyu-icon-lightbulb faa-tada" style="font-size:.9em"></i><span> 闲言碎语</span></a></li><li><a class="site-page child faa-parent animated-hover" href="javascript:toRandomPost()" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-shoe-prints1 faa-tada" style="font-size:.9em"></i><span> 随便逛逛</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/disclaimer/"><i class="fas fa-heart faa-tada"></i><span> 免责声明</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/love/"><i class="anzhiyufont anzhiyu-icon-heartbeat faa-tada" style="font-size:.9em"></i><span> 恋爱小屋</span></a></li></ul></div></div></div><div id="nav-right"><div class="nav-button only-home" id="travellings_button" title="随机前往一个开往项目网站"><a class="site-page" onclick="anzhiyu.totraveling()" title="随机前往一个开往项目网站" href="javascript:void(0);" rel="external nofollow" data-pjax-state="external"><i class="anzhiyufont anzhiyu-icon-train"></i></a></div><div class="nav-button" id="randomPost_button"><a class="site-page" onclick="toRandomPost()" title="随机前往一个文章" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-dice"></i></a></div><div class="nav-button" id="search-button"><a class="site-page social-icon search" href="javascript:void(0);" rel="external nofollow noreferrer" title="搜索🔍" accesskey="s"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span> 搜索</span></a></div><input id="center-console" type="checkbox"><label class="widget" for="center-console" title="中控台" onclick="anzhiyu.switchConsole()"><i class="left"></i><i class="widget center"></i><i class="widget right"></i></label><div id="console"><div class="console-card-group-reward"><ul class="reward-all console-card"><li class="reward-item"><a href="/img/wxpay.webp" target="_blank"><img class="post-qr-code-img" alt="wechat" src="/img/wxpay.webp"></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/img/alipay.webp" target="_blank"><img class="post-qr-code-img" alt="alipay" src="/img/alipay.webp"></a><div class="post-qr-code-desc">alipay</div></li></ul></div><div class="console-card-group"><div class="console-card-group-left"><div class="console-card" id="card-newest-comments"><div class="card-content"><div class="author-content-item-tips">互动</div><span class="author-content-item-title">最新评论</span></div><div class="aside-list"><span>正在加载中...</span></div></div></div><div class="console-card-group-right"><div class="console-card tags"><div class="card-content"><div class="author-content-item-tips">兴趣点</div><span class="author-content-item-title">寻找你感兴趣的领域</span><div class="card-tags"><div class="item-headline"></div><div class="card-tag-cloud"><a href="/tags/API/" style="font-size:1.05rem;color:#637571">API<sup>43</sup></a><a href="/tags/Base64/" style="font-size:1.05rem;color:#8a0460">Base64<sup>1</sup></a><a href="/tags/Collectors/" style="font-size:1.05rem;color:#6b3641">Collectors<sup>3</sup></a><a href="/tags/Date/" style="font-size:1.05rem;color:#5e6603">Date<sup>3</sup></a><a href="/tags/Executor/" style="font-size:1.05rem;color:#abb61f">Executor<sup>9</sup></a><a href="/tags/Guava/" style="font-size:1.05rem;color:#6dc55c">Guava<sup>1</sup></a><a href="/tags/JVM/" style="font-size:1.05rem;color:#8745c2">JVM<sup>8</sup></a><a href="/tags/Java8/" style="font-size:1.05rem;color:#804042">Java8<sup>21</sup></a><a href="/tags/Java9/" style="font-size:1.05rem;color:#21b4c6">Java9<sup>21</sup></a><a href="/tags/Java%E5%B9%B6%E5%8F%91/" style="font-size:1.05rem;color:#0a3988">Java并发<sup>20</sup></a><a href="/tags/Lambda/" style="font-size:1.05rem;color:#29446d">Lambda<sup>4</sup></a><a href="/tags/Lock/" style="font-size:1.05rem;color:#afc378">Lock<sup>1</sup></a><a href="/tags/Maven/" style="font-size:1.05rem;color:#b10843">Maven<sup>1</sup></a><a href="/tags/Memcached/" style="font-size:1.05rem;color:#9663a4">Memcached<sup>23</sup></a><a href="/tags/Mongodb/" style="font-size:1.05rem;color:#b4214d">Mongodb<sup>49</sup></a><a href="/tags/Queue/" style="font-size:1.05rem;color:#220f01">Queue<sup>1</sup></a><a href="/tags/Redis/" style="font-size:1.05rem;color:#c4106c">Redis<sup>27</sup></a><a href="/tags/Stream/" style="font-size:1.05rem;color:#1f5f9f">Stream<sup>4</sup></a><a href="/tags/Thread/" style="font-size:1.05rem;color:#c3563b">Thread<sup>7</sup></a><a href="/tags/Thread-pool/" style="font-size:1.05rem;color:#1a3364">Thread pool<sup>7</sup></a><a href="/tags/forkJoinPool/" style="font-size:1.05rem;color:#1ea132">forkJoinPool<sup>2</sup></a><a href="/tags/stream/" style="font-size:1.05rem;color:#a00679">stream<sup>1</sup></a><a href="/tags/%E4%B8%93%E6%A0%8F/" style="font-size:1.05rem;color:#9e5e9b">专栏<sup>35</sup></a><a href="/tags/%E4%BA%8B%E5%8A%A1/" style="font-size:1.05rem;color:#4d47bc">事务<sup>1</sup></a><a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size:1.05rem;color:#a56245">优化<sup>1</sup></a><a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size:1.05rem;color:#9c8435">命令<sup>57</sup></a><a href="/tags/%E5%AE%89%E8%A3%85/" style="font-size:1.05rem;color:#647e28">安装<sup>6</sup></a><a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size:1.05rem;color:#a192b9">工具<sup>2</sup></a><a href="/tags/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" style="font-size:1.05rem;color:#22a370">数据类型<sup>8</sup></a><a href="/tags/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/" style="font-size:1.05rem;color:#6b985c">生命周期<sup>1</sup></a><a href="/tags/%E7%AE%80%E4%BB%8B/" style="font-size:1.05rem;color:#bc5f40">简介<sup>7</sup></a><a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size:1.05rem;color:#167366">算法<sup>10</sup></a><a href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size:1.05rem;color:#aa928f">设计模式<sup>38</sup></a><a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size:1.05rem;color:#3a740b">配置<sup>2</sup></a><a href="/tags/%E9%9D%A2%E8%AF%95/" style="font-size:1.05rem;color:#75c343">面试<sup>11</sup></a></div></div><hr></div></div><div class="console-card history"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-box-archiv"></i><span>文章</span></div><div class="card-archives"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-archive"></i><span>归档</span><a class="card-more-btn" href="/archives/" title="查看更多"> <i class="anzhiyufont anzhiyu-icon-angle-right"></i></a></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">2</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/05/"><span class="card-archive-list-date">五月 2021</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">2</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/10/"><span class="card-archive-list-date">十月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">21</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/09/"><span class="card-archive-list-date">九月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">44</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/08/"><span class="card-archive-list-date">八月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">47</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/07/"><span class="card-archive-list-date">七月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">42</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/06/"><span class="card-archive-list-date">六月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">31</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/05/"><span class="card-archive-list-date">五月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">43</span><span>篇</span></div></a></li></ul></div><hr></div></div></div><div class="button-group"><div class="console-btn-item"><a class="darkmode_switchbutton" title="显示模式切换" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-moon"></i></a></div><div class="console-btn-item" id="consoleHideAside" onclick="anzhiyu.hideAsideBtn()" title="边栏显示控制"><a class="asideSwitch"><i class="anzhiyufont anzhiyu-icon-arrows-left-right"></i></a></div><div class="console-btn-item on" id="consoleCommentBarrage" onclick="anzhiyu.switchCommentBarrage()" title="热评开关"><a class="commentBarrage"><i class="anzhiyufont anzhiyu-icon-message"></i></a></div><div class="console-btn-item" id="consoleMusic" onclick="anzhiyu.musicToggle()" title="音乐开关"><a class="music-switch"><i class="anzhiyufont anzhiyu-icon-music"></i></a></div></div><div class="console-mask" onclick="anzhiyu.hideConsole()" href="javascript:void(0);" rel="external nofollow noreferrer"></div></div><div class="nav-button" id="nav-totop"><a class="totopbtn" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i><span id="percent" onclick="anzhiyu.scrollToDest(0,500)">0</span></a></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer" title="切换"><i class="anzhiyufont anzhiyu-icon-bars"></i></a></div></div></div></nav><div id="post-info"><div id="post-firstinfo"><div class="meta-firstline"><a class="post-meta-original">原创</a><span class="article-meta tags"></span></div></div><h1 class="post-title" itemprop="name headline">二十二、Gradle Java 插件</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="anzhiyufont anzhiyu-icon-calendar-days post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" itemprop="dateCreated datePublished" datetime="2020-03-22T14:29:54.000Z" title="发表于 2020-03-22 22:29:54">2020-03-22</time><span class="post-meta-separator"></span><i class="anzhiyufont anzhiyu-icon-history post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" itemprop="dateCreated datePublished" datetime="2020-03-22T14:29:54.000Z" title="更新于 2020-03-22 22:29:54">2020-03-22</time></span></div><div class="meta-secondline"><span class="post-meta-separator"></span><span class="post-meta-wordcount"><i class="anzhiyufont anzhiyu-icon-file-word post-meta-icon" title="文章字数"></i><span class="post-meta-label" title="文章字数">字数总计:</span><span class="word-count" title="文章字数">6.8k</span><span class="post-meta-separator"></span><i class="anzhiyufont anzhiyu-icon-clock post-meta-icon" title="阅读时长"></i><span class="post-meta-label" title="阅读时长">阅读时长:</span><span>23分钟</span></span><span class="post-meta-separator"></span><span class="post-meta-pv-cv" data-flag-title="二十二、Gradle Java 插件"><i class="anzhiyufont anzhiyu-icon-fw-eye post-meta-icon"></i><span class="post-meta-label" title="阅读量">阅读量:</span><span id="busuanzi_value_page_pv"><i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-spin"></i></span></span><span class="post-meta-separator"> </span><span class="post-meta-position" title="作者IP属地为武汉"><i class="anzhiyufont anzhiyu-icon-location-dot"></i>武汉</span></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section><div id="post-top-cover"><img class="nolazyload" id="post-top-bg" src="https://www.bing.com/th?id=OHR.DarkSkyAcadia_EN-US6966527964_UHD.jpg"></div></header><main id="blog-container"><div class="layout" id="content-inner"><div id="post"><div class="post-ai-description"><div class="ai-title"><i class="anzhiyufont anzhiyu-icon-bilibili"></i><div class="ai-title-text">AI-摘要</div><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right"></i><i class="anzhiyufont anzhiyu-icon-circle-dot" title="朗读摘要"></i><div id="ai-tag">Tianli GPT</div></div><div class="ai-explanation">AI初始化中...</div><div class="ai-btn-box"><div class="ai-btn-item">介绍自己 🙈</div><div class="ai-btn-item">生成本文简介 👋</div><div class="ai-btn-item">推荐相关文章 📖</div><div class="ai-btn-item">前往主页 🏠</div><div class="ai-btn-item" id="go-tianli-blog">前往爱发电购买</div></div><script data-pjax src="/js/anzhiyu/ai_abstract.js"></script></div><article class="post-content" id="article-container" itemscope itemtype="https://it985.github.io/posts/e35ffad1.html"><header><h1 id="CrawlerTitle" itemprop="name headline">二十二、Gradle Java 插件</h1><span itemprop="author" itemscope itemtype="http://schema.org/Person">云少</span><time itemprop="dateCreated datePublished" datetime="2020-03-22T14:29:54.000Z" title="发表于 2020-03-22 22:29:54">2020-03-22</time><time itemprop="dateCreated datePublished" datetime="2020-03-22T14:29:54.000Z" title="更新于 2020-03-22 22:29:54">2020-03-22</time></header><h1 id="二十二、Gradle-Java-插件"><a href="#二十二、Gradle-Java-插件" class="headerlink" title="二十二、Gradle Java 插件"></a>二十二、Gradle Java 插件</h1><p>Java 插件向一个项目添加了 Java 编译、 测试和 bundling 的能力。它是很多其他 Gradle 插件的基础服务。</p><h2 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h2><p>要使用 Java 插件，请在构建脚本中加入：</p><p><strong>使用 Java 插件</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apply plugin: <span class="string">&#x27;java&#x27;</span>  </span><br></pre></td></tr></table></figure><h2 id="源集"><a href="#源集" class="headerlink" title="源集"></a>源集</h2><p>Java 插件引入了一个源集的概念。一个源集只是一组用于编译并一起执行的源文件。这些源文件可能包括 Java 源代码文件和资源文件。其他有一些插件添加了在源集里包含 Groovy 和 Scala 的源代码文件的能力。一个源集有一个相关联的编译类路径和运行时类路径。</p><p>源集的一个用途是，把源文件进行逻辑上的分组，以描述它们的目的。例如，你可能会使用一个源集来定义一个集成测试套件，或者你可能会使用单独的源集来定义你的项目的 API 和实现类。</p><p>Java 插件定义了两个标准的源集，分别是 main 和 test。main 源集包含你产品的源代码，它们将被编译并组装成一个 JAR 文件。test 源集包含你的单元测试的源代码，它们将被编译并使用 JUnit 或 TestNG 来执行。</p><h2 id="任务"><a href="#任务" class="headerlink" title="任务"></a>任务</h2><p>Java 插件向你的项目添加了大量的任务，如下所示。</p><p>表 Java 插件-任务</p><table><thead><tr><th>任务名称</th><th>依赖于</th><th>类型</th><th>描述</th></tr></thead><tbody><tr><td><code>compileJava</code></td><td>产生编译类路径中的所有任务。这包括了用于<code>jar</code>任务。</td><td>JavaCompile</td><td>使用 javac 编译产品中的 Java 源文件。</td></tr><tr><td><code>processResources</code></td><td>–</td><td>Copy</td><td>把生产资源文件拷贝到生产的类目录中。</td></tr><tr><td><code>classes</code></td><td><code>processResources</code>。一些插件添加了额外的编译任务。</td><td>Task</td><td>组装生产的类目录。</td></tr><tr><td><code>compileTestJava</code></td><td><code>compile</code>，再加上所有能产生测试编译类路径的任务。</td><td>JavaCompile</td><td>使用 javac 编译 Java 的测试源文件。</td></tr><tr><td><code>processTestResources</code></td><td>–</td><td>Copy</td><td>把测试的资源文件拷贝到测试的类目录中。</td></tr><tr><td><code>testClasses</code></td><td><code>processTestResources</code>。一些插件添加了额外的测试编译任务。</td><td>Task</td><td>组装测试的类目录。</td></tr><tr><td><code>jar</code></td><td><code>compile</code></td><td>Jar</td><td>组装 JAR 文件</td></tr><tr><td><code>javadoc</code></td><td><code>compile</code></td><td>Javadoc</td><td>使用 Javadoc 生成生产的 Java 源代码的API文档</td></tr><tr><td><code>test</code></td><td><code>compileTest</code>，再加上所有产生测试运行时类路径的任务。</td><td>Test</td><td>使用 JUnit 或 TestNG运行单元测试。</td></tr><tr><td><code>uploadArchives</code></td><td>使用<code>jar</code>。</td><td>Upload</td><td>使用<code>archives</code>配置上传包括 JAR 文件的构件。</td></tr><tr><td><code>clean</code></td><td>–</td><td>Delete</td><td>删除项目的 build 目录。</td></tr><tr><td><code>TaskName</code></td><td>–</td><td>Delete</td><td>删除由指定的任务所产生的输出文件。例如， <code>jar</code>任务中所创建的 JAR 文件，<code>test</code>任务所创建的测试结果。</td></tr></tbody></table><p>对于每个你添加到该项目中的源集，Java 插件将添加以下的编译任务：</p><p>表 Java 插件-源集任务</p><table><thead><tr><th>任务名称</th><th>依赖于</th><th>类型</th><th>描述</th></tr></thead><tbody><tr><td><code>SourceSet</code>Java</td><td>所有产生源集编译类路径的任务。</td><td>JavaCompile</td><td>使用 javac 编译给定的源集中的 Java 源文件。</td></tr><tr><td><code>SourceSet</code>Resources</td><td>–</td><td>Copy</td><td>把给定的源集的资源文件拷贝到类目录中。</td></tr><tr><td><code>sourceSet</code>Classes</td><td><code>SourceSet</code>Resources。某些插件还为源集添加了额外的编译任务。</td><td>Task</td><td>组装给定源集的类目录。</td></tr></tbody></table><p>Java 插件还增加了大量的任务构成该项目的生命周期：</p><p>表 Java 插件-生命周期任务</p><table><thead><tr><th>任务名称</th><th>依赖于</th><th>类型</th><th>描述</th></tr></thead><tbody><tr><td><code>assemble</code></td><td>项目中的所有归档项目，包括<code>jar</code>任务。某些插件还向项目添加额外的归档任务。</td><td>Task</td><td>组装项目中所有的归类文件。</td></tr><tr><td><code>check</code></td><td>项目中的所有核查项目，包括<code>test</code>任务。某些插件还向项目添加额外的核查任务。</td><td>Task</td><td>执行项目中所有的核查任务。</td></tr><tr><td><code>build</code></td><td><code>assemble</code></td><td>Task</td><td>执行项目的完事构建。</td></tr><tr><td><code>buildNeeded</code></td><td><code>build</code>任务。</td><td>Task</td><td>执行项目本身及它所依赖的其他所有项目的完整构建。</td></tr><tr><td><code>buildDependents</code></td><td><code>build</code>任务。</td><td>Task</td><td>执行项目本身及依赖它的其他所有项目的完整构建。</td></tr><tr><td><code>ConfigurationName</code></td><td>使用配置ConfigurationName生成构件的任务。</td><td>Task</td><td>组装指定配置的构件。该任务由Base插件添加，并由Java插件隐式实现。</td></tr><tr><td><code>ConfigurationName</code></td><td>使用配置ConfigurationName上传构件的任务。</td><td>Upload</td><td>组装并上传指定配置的构件。该任务由Base插件添加，并由Java插件隐式实现。</td></tr></tbody></table><p>uploadConfigurationName 使用配置 ConfigurationName 上传构件的任务。 Upload 组装并上传指定配置的构件。该任务由 Base 插件添加，并由 Java 插件隐式实现。</p><h2 id="项目布局"><a href="#项目布局" class="headerlink" title="项目布局"></a>项目布局</h2><p>Java 插件会假定如下所示的项目布局。这些目录都不需要一定存在，或者是里面有什么内容。Java 插件将会进行编译，不管它发现什么，并处理缺少的任何东西。</p><p>表 Java 插件-默认项目布局</p><table><thead><tr><th>目录</th><th>意义</th></tr></thead><tbody><tr><td><code>src/main/java</code></td><td>产品的Java源代码</td></tr><tr><td><code>src/main/resources</code></td><td>产品的资源</td></tr><tr><td><code>src/test/java</code></td><td>Java 测试源代码</td></tr><tr><td><code>src/test/resources</code></td><td>测试资源</td></tr><tr><td><code>sourceSet</code>&#x2F;java</td><td>给定的源集的Java源代码</td></tr><tr><td><code>sourceSet</code>&#x2F;resources</td><td>给定的源集的资源</td></tr></tbody></table><h2 id="更改项目布局"><a href="#更改项目布局" class="headerlink" title="更改项目布局"></a>更改项目布局</h2><p>你可以通过配置适当的源集，来配置项目的布局。这一点将在以下各节中详细讨论。这里是如何更改 main Java 和资源源目录的一个简短的例子。</p><p><strong>自定义 Java 源代码布局</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    main &#123;</span><br><span class="line">        java &#123;</span><br><span class="line">            srcDir <span class="string">&#x27;src/java&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        resources &#123;</span><br><span class="line">            srcDir <span class="string">&#x27;src/resources&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><h2 id="依赖管理"><a href="#依赖管理" class="headerlink" title="依赖管理"></a>依赖管理</h2><p>Java 插件向项目添加了许多依赖配置，如下图所示。它对一些任务指定了这些配置，如 compileJava 和 test。</p><p>表Java插件 – 依赖配置</p><table><thead><tr><th>名称</th><th>继承自</th><th>在哪些任务中使用</th><th>意义</th></tr></thead><tbody><tr><td>compile</td><td>–</td><td>compileJava</td><td>编译时依赖</td></tr><tr><td>runtime</td><td>compile</td><td>–</td><td>运行时依赖</td></tr><tr><td>testCompile</td><td>compile</td><td>compileTestJava</td><td>用于编译测试的其他依赖</td></tr><tr><td>testRuntime</td><td>runtime, testCompile</td><td>test</td><td>只用于运行测试的其他依赖</td></tr><tr><td>archives</td><td>–</td><td>uploadArchives</td><td>由本项目生产的构件（如jar包）。</td></tr><tr><td>default</td><td>runtime</td><td>–</td><td>本项目上的默认项目依赖配置。包含本项目运行时所需要的构件和依赖。</td></tr></tbody></table><p>对于每个你添加到项目中的源集，Java 插件都会添加以下的依赖配置：</p><p>表 Java 插件 – 源集依赖配置</p><table><thead><tr><th>名称</th><th>继承自</th><th>在哪些任务中使用</th><th>意义</th></tr></thead><tbody><tr><td>sourceSetCompile</td><td>–</td><td>compileSourceSetJava</td><td>给定源集的编译时依赖</td></tr><tr><td>sourceSetRuntime</td><td>sourceSetCompile</td><td>–</td><td>给定源集的运行时依赖</td></tr></tbody></table><h2 id="常规属性"><a href="#常规属性" class="headerlink" title="常规属性"></a>常规属性</h2><p>Java 插件向项目添加了许多常规属性，如下图所示。您可以在构建脚本中使用这些属性，就像它们是 project 对象的属性一样。</p><p>表 Java 插件 – 目录属性</p><table><thead><tr><th>属性名称</th><th>类型</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td><code>reportsDirName</code></td><td><code>String</code></td><td><code>reports</code></td><td>相对于build目录的目录名称，报告将生成到此目录。</td></tr><tr><td><code>reportsDir</code></td><td><code>File</code> (read-only)</td><td><code>reportsDirName</code></td><td>报告将生成到此目录。</td></tr><tr><td><code>testResultsDirName</code></td><td><code>String</code></td><td><code>test-results</code></td><td>相对于build目录的目录名称，测试报告的.xml文件将生成到此目录。</td></tr><tr><td><code>testResultsDir</code></td><td><code>File</code> (read-only)</td><td><code>testResultsDirName</code></td><td>测试报告的.xml文件将生成到此目录。</td></tr><tr><td><code>testReportDirName</code></td><td><code>String</code></td><td><code>tests</code></td><td>相对于build目录的目录名称，测试报告将生成到此目录。</td></tr><tr><td><code>testReportDir</code></td><td><code>File</code> (read-only)</td><td><code>testReportDirName</code></td><td>测试报告生成到此目录。</td></tr><tr><td><code>libsDirName</code></td><td><code>String</code></td><td><code>libs</code></td><td>相对于build目录的目录名称，类库将生成到此目录中。</td></tr><tr><td><code>libsDir</code></td><td><code>File</code> (read-only)</td><td><code>libsDirName</code></td><td>类库将生成到此目录中。</td></tr><tr><td><code>distsDirName</code></td><td><code>String</code></td><td><code>distributions</code></td><td>相对于build目录的目录名称，发布的文件将生成到此目录中。</td></tr><tr><td><code>distsDir</code></td><td><code>File</code> (read-only)</td><td><code>distsDirName</code></td><td>要发布的文件将生成到此目录。</td></tr><tr><td><code>docsDirName</code></td><td><code>String</code></td><td><code>docs</code></td><td>相对于build目录的目录名称，文档将生成到此目录。</td></tr><tr><td><code>docsDir</code></td><td><code>File</code> (read-only)</td><td><code>docsDirName</code></td><td>要生成文档的目录。</td></tr><tr><td><code>dependencyCacheDirName</code></td><td><code>String</code></td><td><code>dependency-cache</code></td><td>相对于build目录的目录名称，该目录用于缓存源代码的依赖信息。</td></tr><tr><td><code>dependencyCacheDir</code></td><td><code>File</code> (read-only)</td><td><code>dependencyCacheDirName</code></td><td>该目录用于缓存源代码的依赖信息。</td></tr></tbody></table><p>表 Java 插件 – 其他属性</p><table><thead><tr><th>属性名称</th><th>类型</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td><code>sourceSets</code></td><td>SourceSetContainer (read-only)</td><td>非空</td><td>包含项目的源集。</td></tr><tr><td><code>sourceCompatibility</code></td><td>JavaVersion. 可以使用字符串或数字来设置，例如<code>1.5</code>。</td><td>当前JVM所使用的值</td><td>当编译Java源代码时所使用的Java版本兼容性。</td></tr><tr><td><code>targetCompatibility</code></td><td>JavaVersion. 可以使用字符串或数字来设置，例如<code>1.5</code>。</td><td><code>sourceCompatibility</code></td><td>要生成的类的 Java 版本。</td></tr><tr><td><code>archivesBaseName</code></td><td><code>String</code></td><td><code>projectName</code></td><td>像JAR或ZIP文件这样的构件的basename</td></tr><tr><td><code>manifest</code></td><td>Manifest</td><td>一个空的清单</td><td>要包括的所有 JAR 文件的清单。</td></tr></tbody></table><p>这些属性由 JavaPluginConvention， BasePluginConvention 和 ReportingBasePluginConvention 这些类型的常规对象提供。</p><h2 id="使用源集"><a href="#使用源集" class="headerlink" title="使用源集"></a>使用源集</h2><p>你可以使用 sourceSets 属性访问项目的源集。这是项目的源集的容器，它的类型是 SourceSetContainer。除此之后，还有一个 sourceSets {}的脚本块，可以传入一个闭包来配置源集容器。源集容器的使用方式几乎与其他容器一样，例如 tasks。</p><p><strong>访问源集</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Various ways to access the main source set</span></span><br><span class="line"><span class="keyword">println</span> <span class="keyword">sourceSets</span>.main.output.classesDir</span><br><span class="line"><span class="keyword">println</span> <span class="keyword">sourceSets</span>[<span class="string">&#x27;main&#x27;</span>].output.classesDir</span><br><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    <span class="keyword">println</span> main.output.classesDir</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    main &#123;</span><br><span class="line">        <span class="keyword">println</span> output.classesDir</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Iterate over the source sets</span></span><br><span class="line"><span class="keyword">sourceSets</span>.all &#123;</span><br><span class="line">    <span class="keyword">println</span> name</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>要配置一个现有的源集，你只需使用上面的其中一种访问方法来设置源集的属性。这些属性将在下文中进行介绍。下面是一个配置 main 的 Java 和资源目录的例子：</p><p><strong>配置源集的源代码目录</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    main &#123;</span><br><span class="line">        java &#123;</span><br><span class="line">            srcDir <span class="string">&#x27;src/java&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        resources &#123;</span><br><span class="line">            srcDir <span class="string">&#x27;src/resources&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><h2 id="源集属性"><a href="#源集属性" class="headerlink" title="源集属性"></a>源集属性</h2><p>下表列出了一些重要的源集属性。你可以在 SourceSet 的 API 文档中查看更多的详细信息。</p><p>表 Java 插件 – 源集属性</p><table><thead><tr><th>属性名称</th><th>类型</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>String</code> (read-only)</td><td>非空</td><td>用来确定一个源集的源集名称。</td></tr><tr><td><code>output</code></td><td>SourceSetOutput (read-only)</td><td>非空</td><td>源集的输出文件，包含它编译过的类和资源。</td></tr><tr><td><code>output.classesDir</code></td><td><code>File</code></td><td><code>name</code></td><td>要生成的该源集的类的目录。</td></tr><tr><td><code>output.resourcesDir</code></td><td><code>File</code></td><td><code>name</code></td><td>要生成的该源集的资源的目录。</td></tr><tr><td><code>compileClasspath</code></td><td>FileCollection</td><td><code>SourceSet</code> 配置。</td><td>该类路径在编译该源集的源文件时使用。</td></tr><tr><td><code>runtimeClasspath</code></td><td>FileCollection</td><td><code>SourceSet</code> 配置。</td><td>该类路径在执行该源集的类时使用。</td></tr><tr><td><code>java</code></td><td>SourceDirectorySet (read-only)</td><td>非空</td><td>该源集的Java源文件。仅包含Java源文件目录里的<code>.java</code>文件，并排除其他所有文件。</td></tr><tr><td><code>java.srcDirs</code></td><td><code>Set&lt;File&gt;</code></td><td><code>name</code>&#x2F;java]</td><td>该源目录包含了此源集的所有Java源文件。</td></tr><tr><td><code>resources</code></td><td>SourceDirectorySet (read-only)</td><td>非空</td><td>此源集的资源文件。仅包含资源文件，并且排除在资源源目录中找到的所有 <code>.java</code>文件。其他插件，如Groovy 插件，会从该集合中排除其他类型的文件。</td></tr><tr><td><code>resources.srcDirs</code></td><td><code>Set&lt;File&gt;</code></td><td><code>name</code>&#x2F;resources]</td><td>该源目录包含了此源集的资源文件。</td></tr><tr><td><code>allJava</code></td><td>SourceDirectorySet (read-only)</td><td><code>java</code></td><td>该源集的所有<code>.java</code> 文件。有些插件，如Groovy 插件，会从该集合中增加其他的Java源文件。</td></tr><tr><td><code>allSource</code></td><td>SourceDirectorySet (read-only)</td><td><code>resources + java</code></td><td>该源集的所有源文件。包含所有的资源文件和Java源文件。有些插件，如Groovy 插件，会从该集合中增加其他的源文件。</td></tr></tbody></table><h3 id="定义新的源集"><a href="#定义新的源集" class="headerlink" title="定义新的源集"></a>定义新的源集</h3><p>要定义一个新的源集，你只需在 sourceSets {}块中引用它。下面是一个示例：</p><p><strong>定义一个源集</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    intTest</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>当您定义一个新的源集时，Java 插件会为该源集添加一些依赖配置，如表 23.6，“Java 插件 – 源集依赖项配置”所示。你可以使用这些配置来定义源集的编译和运行时的依赖。</p><p><strong>定义源集依赖</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">sourceSets</span> &#123;</span><br><span class="line">    intTest</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">dependencies</span> &#123;</span><br><span class="line">    intTestCompile <span class="string">&#x27;junit:junit:4.11&#x27;</span></span><br><span class="line">    intTestRuntime <span class="string">&#x27;org.ow2.asm:asm-all:4.0&#x27;</span></span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>Java 插件还添加了大量的任务，用于组装源集的类，如表 23.2，“Java 插件 – 源设置任务”所示。例如，对于一个被叫做 intTest 的源集，你可以运行 gradle intTestClasses 来编译 int 测试类。</p><p><strong>编译源集</strong></p><p>gradle intTestClasses的输出结果</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt; gradle intTestClasses</span><br><span class="line">:compileIntTestJava</span><br><span class="line">:processIntTestResources</span><br><span class="line">:intTestClasses</span><br><span class="line">BUILD SUCCESSFUL</span><br><span class="line">Total time: 1 secs  </span><br></pre></td></tr></table></figure><h2 id="一些源集的范例"><a href="#一些源集的范例" class="headerlink" title="一些源集的范例"></a>一些源集的范例</h2><p>添加一个包含了源集的类的 JAR 包</p><p><strong>示例为一个源集装配一个JAR文件</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">task</span> intTestJar(type: Jar) &#123;</span><br><span class="line">    <span class="keyword">from</span> <span class="keyword">sourceSets</span>.intTest.output</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>为一个源集生成 Javadoc：</p><p><strong>示例为一个源集生成 Javadoc：</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">task</span> intTestJavadoc(type: Javadoc) &#123;</span><br><span class="line">    <span class="keyword">source</span> <span class="keyword">sourceSets</span>.intTest.allJava</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>添加一个测试套件以运行一个源集里的测试</p><p><strong>示例 运行源集里的测试</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">task</span> intTest(type: Test) &#123;</span><br><span class="line">    testClassesDir = <span class="keyword">sourceSets</span>.intTest.output.classesDir</span><br><span class="line">    <span class="keyword">classpath</span> = <span class="keyword">sourceSets</span>.intTest.runtimeClasspath</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><h2 id="Javadoc"><a href="#Javadoc" class="headerlink" title="Javadoc"></a>Javadoc</h2><p>Javadoc 任务是 Javadoc 的一个实例。它支持核心的 javadoc 参数选项，以及在 Javadoc 可执行文件的参考文档中描述的标准 doclet 参数选项。对于支持的 Javadoc 参数选项的完整列表，请参考下面的类的 API 文档： CoreJavadocOptions 和StandardJavadocDocletOptions。</p><p>表 Java 插件 – Javadoc 属性</p><table><thead><tr><th>任务属性</th><th>类型</th><th>默认值</th></tr></thead><tbody><tr><td><code>classpath</code></td><td>FileCollection</td><td><code>sourceSets.main.output + sourceSets.main.compileClasspath</code></td></tr><tr><td><code>source</code></td><td>FileTree.</td><td><code>sourceSets.main.allJava</code></td></tr><tr><td><code>destinationDir</code></td><td><code>File</code></td><td><code>docsDir</code>&#x2F;javadoc</td></tr><tr><td><code>title</code></td><td><code>String</code></td><td>project的名称和版本</td></tr></tbody></table><h2 id="清理"><a href="#清理" class="headerlink" title="清理"></a>清理</h2><p>clean 任务是 Delete 的一个实例。它只是删除由其 dir 属性表示的目录。</p><p>表 Java 插件 – Clean 性能</p><table><thead><tr><th>任务属性</th><th>类型</th><th>默认值</th></tr></thead><tbody><tr><td><code>dir</code></td><td><code>File</code></td><td><code>buildDir</code></td></tr></tbody></table><h2 id="资源"><a href="#资源" class="headerlink" title="资源"></a>资源</h2><p>Java 插件使用 Copy 任务进行资源的处理。它为该 project 里的每个源集添加一个实例。</p><p>表 Java 插件-ProcessResources 属性</p><table><thead><tr><th>任务属性</th><th>类型</th><th>默认值</th></tr></thead><tbody><tr><td><code>srcDirs</code></td><td><code>Object</code>.</td><td><code>sourceSet</code>.resources</td></tr><tr><td><code>destinationDir</code></td><td><code>16.1 章节，“查找文件”中所讲到的任何一种方式来设置。</code></td><td><code>sourceSet</code>.output.resourcesDir</td></tr></tbody></table><h2 id="CompileJava"><a href="#CompileJava" class="headerlink" title="CompileJava"></a>CompileJava</h2><p>Java 插件为该 project 里的每个源集添加一个 JavaCompile 实例。一些最常见的配置选项如下所示。</p><p>表 Java 插件- Compile 属性</p><table><thead><tr><th>任务属性</th><th>类型</th><th>默认值</th></tr></thead><tbody><tr><td><code>classpath</code></td><td>FileCollection</td><td><code>sourceSet</code>.compileClasspath</td></tr><tr><td><code>source</code></td><td>FileTree</td><td><code>sourceSet</code>.java</td></tr><tr><td><code>destinationDir</code></td><td><code>File</code>.</td><td><code>sourceSet</code>.output.classesDir</td></tr></tbody></table><p>compile 任务委派了 Ant 的 javac 任务。将 options.useAnt 设置为 false 将绕过 Ant 任务，而激活 Gradle 的直接编译器集成。在未来的 Gradle 版本中，将把它作为默认设置。</p><p>默认情况下，Java 编译器在 Gradle 过程中运行。将 options.fork 设置为 true 将会使编译出现在一个单独的进程中。在 Ant javac 任务中，这意味着将会为每一个 compile 任务fork 一个新的进程，而这将会使编译变慢。相反，Gradle 的直接编译器集成 （见上文） 将尽可能多地重用相同的编译器进程。在这两种情况下，使用 options.forkOptions 指定的所有fork 选项都将得到重视。</p><h2 id="Test"><a href="#Test" class="headerlink" title="Test"></a>Test</h2><p>test 任务是 Test 的一个实例。它会自动检测和执行 test 源集中的所有单元测试。测试执行完成后，它还会生成一份报告。同时支持 JUnit 和 TestNG。可以看一看Test的完整的 API。</p><h3 id="测试执行"><a href="#测试执行" class="headerlink" title="测试执行"></a>测试执行</h3><p>测试在单独的 JVM 中执行，与 main 构建进程隔离。Test 任务的 API 可以让你控制什么时候开始。</p><p>有大量的属性用于控制测试进程的启动。这包括系统属性、 JVM 参数和使用的 Java 可执行文件。</p><p>你可以指定是否要并行运行你的测试。Gradle 通过同时运行多个测试进程来提供并行测试的执行。每个测试进程会依次执行一个单一的测试，所以你一般不需要对你的测试做任何的配置来利用这一点。 MaxParallelForks 属性指定在给定的时间可以运行的测试进程的最大数。它的默认值是 1，也就是说，不并行执行测试。</p><p>测试进程程会为其将 org.gradle.test.worker 系统属性设置为一个唯一标识符，这个标识符可以用于文件名称或其他资源标识符。</p><p>你可以指定在执行了一定数量的测试类之后，重启那个测试进程。这是一个很有用的替代方案，让你的测试进程可以有很大的堆内存。forkEvery 属性指定了要在测试进程中执行的测试类的最大数。默认是每个测试进程中执行的测试数量不限。</p><p>该任务有一个 ignoreFailures 属性，用以控制测试失败时的行为。test 会始终执行它检测到的每一个测试。如果 ignoreFailures 为 false，并且有测试不通过，那它会停止继续构建。IgnoreFailures 的默认值为 false。</p><p>testLogging 属性可以配置哪些测试事件需要记录，并且使用什么样的日志级别。默认情况下，对于每个失败的测试都只会打印一个简洁的消息。请参阅 TestLoggingContainer，查看如何把你的测试日志打印调整为你的偏好设置。</p><h3 id="调试"><a href="#调试" class="headerlink" title="调试"></a>调试</h3><p>test 任务提供了一个 Test.getDebug()属性，可以设置为启动，使 JVM 在执行测试之前，等待一个 debugger 连接到它的 5005 端口上。</p><p>这也可以在调用时通过–debug-vm task 选项进行启用。</p><h3 id="测试过滤"><a href="#测试过滤" class="headerlink" title="测试过滤"></a>测试过滤</h3><p>从 Gradle 1.10 开始，可以根据测试的名称模式，只包含指定的测试。过滤，相对于测试类的包含或排除，是一个不同的机制。它将在接下来的段落中进行描述（-Dtest.single， test.include 和 friends）。后者基于文件，比如测试实现类的物理位置。file-level 的测试选择不支持的很多有趣的情况，都可以用 test-level 过滤来做到。以下这些场景中，有一些 Gradle 现在就可以处理，而有一些则将在未来得到实现：</p><ul><li>在指定的测试的方法级别上进行过滤；执行单个测试方法</li><li>基于自定义注解（以后实现）进行过滤</li><li>基于测试层次结构进行过滤 ；执行所有继承了某一基类（以后实现） 的测试</li><li>基于一些自定义的运行时的规则进行过滤，例如某个系统属性或一些静态的特定值（以后实现）</li></ul><p>测试过滤功能具有以下的特征：</p><ul><li>支持完整的限定类名称或完整的限定的方法名称，例如“org.gradle.SomeTest”、“org.gradle.SomeTest.someMethod”</li><li>通配符 “*” 支付匹配任何字符</li><li>提供了“–tests”的命令行选项，以方便地设置测试过滤器。这对“单一测试方法的执行”的经典用例特别有用。当使用该命令行选项选项时，在构建脚本中声明的列入过滤器的测试将会被忽略。</li><li>Gradle 尽最大努力对有着特定的测试框架 API 的局限的测试进行过滤。一些高级的、 综合的测试可能不完全符合过滤条件。然而，绝大多数的测试和用例都会被很好地处理。</li><li>测试过滤将会取代基于文件的测试选择。后者可能在将来会被完全地取代掉。我们将会继续改进测试过滤的 API，并添加更多种类的过滤器。</li></ul><p><strong>在构建脚本中过滤测试</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">test &#123;</span><br><span class="line">    filter &#123;</span><br><span class="line">        <span class="comment">//include specific method in any of the tests</span></span><br><span class="line">        includeTestsMatching <span class="string">&quot;*UiCheck&quot;</span></span><br><span class="line">        <span class="comment">//include all tests from package</span></span><br><span class="line">        includeTestsMatching <span class="string">&quot;org.gradle.internal.*&quot;</span></span><br><span class="line">        <span class="comment">//include all integration tests</span></span><br><span class="line">        includeTestsMatching <span class="string">&quot;*IntegTest&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>有关更多的详细信息和示例，请参阅 TestFilter 的文档。</p><p>使用命令行选项的一些示例：</p><ul><li>gradle test –tests org.gradle.SomeTest.someSpecificFeature</li><li>gradle test –tests *SomeTest.someSpecificFeature</li><li>gradle test –tests *SomeSpecificTest</li><li>gradle test –tests all.in.specific.package*</li><li>gradle test –tests *IntegTest</li><li>gradle test –tests <em>IntegTest</em>ui*</li><li>gradle someTestTask –tests <em>UiTest someOtherTestTask –tests</em> WebTest*ui</li></ul><h3 id="通过系统属性执行单一的测试"><a href="#通过系统属性执行单一的测试" class="headerlink" title="通过系统属性执行单一的测试"></a>通过系统属性执行单一的测试</h3><p>这种机制已经被上述的“测试过滤”所取代。 设置一个 taskName.single &#x3D; testNamePattern 的系统属性将会只执行匹配 testNamePattern 的那些测试。这个 taskName 可以是一个完整的多项目路径，比如“sub1:sub2:test”，或者仅是一个任务名称。testNamePattern 将用于形成一个“**&#x2F;testNamePattern*.class” 的包含模式。如果这个模式无法找到任何测试，那么将会抛出一个异常。这是为了使你不会误以为测试通过。如果执行了一个以上的子项目的测试，该模式会被应用于每一个子项目中。如果在一个特定的子项目中，找不到测试用例，那么将会抛出异常。在这种情况下你可以使用路径标记法的模式，这样该模式就会只应用于特定的子项目的测试任务中。或者你可以指定要执行的任务的完整限定名称。你还可以指定多个模式。示例：</p><ul><li>gradle -Dtest.single&#x3D;ThisUniquelyNamedTest test</li><li>gradle -Dtest.single&#x3D;a&#x2F;b&#x2F; test</li><li>gradle -DintegTest.single&#x3D;*IntegrationTest integTest</li><li>gradle -Dtest.single&#x3D;:proj1:test:Customer build</li><li>gradle -DintegTest.single&#x3D;c&#x2F;d&#x2F; :proj1:integTest</li></ul><h3 id="测试检测"><a href="#测试检测" class="headerlink" title="测试检测"></a>测试检测</h3><p>Test 任务通过检查编译过的测试类来检测哪些类是测试类。默认情况下它会扫描所有的.class 文件。您可以设置自定义的 includes 或 excludes，这样就只有这些类才会被扫描。根据所使用的测试框架 （JUnit 或 TestNG），会使用不同的标准进行测试类的检测。</p><p>当使用 JUnit 时，我们扫描 JUnit 3 和 4 的测试类。如果满足以下的任何一个条件，这个类就被认为是一个 JUnit 测试类：</p><ul><li>类或超类继承自 TestCase 或 GroovyTestCase</li><li>类或超类使用了 @RunWith 进行注解</li><li>类或超类含有一个带 @Test 注解的方法</li></ul><p>当使用 TestNG 时，我们扫描所有带有 @Test 注解的方法。</p><p>请注意，抽象类不会被执行。Gradle 还将扫描测试类路径中的 jar 文件里的继承树。</p><p>如果你不想要使用测试类检测，可以通过设置 scanForTestClasses 为 false 来禁用它。这将使test任务只使用 includes &#x2F; excludes 来找到测试类。如果 scanForTestClasses 为disabled，并且没有指定 include 或 exclude 模式，则使用各自的默认值。对于 include 的默认值是 “**&#x2F;*Tests.class”， “*<em>&#x2F;*Test.class”，而对于exclude它的默认值是 “</em><em>&#x2F;Abstract</em>.class”。</p><h3 id="测试分组"><a href="#测试分组" class="headerlink" title="测试分组"></a>测试分组</h3><p>JUnit 和 TestNG 可以对测试方法进行复杂的分组。</p><p>为对 Junit 测试类和方法进行分组，JUnit 4.8 引入了类别的概念。test 任务可以实现一个规范，让你 include 和 exclude 想要的 JUnit 类别。</p><p><strong>JUnit 类别</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">test &#123;</span><br><span class="line">    useJUnit &#123;</span><br><span class="line">        includeCategories <span class="string">&#x27;org.gradle.junit.CategoryA&#x27;</span></span><br><span class="line">        excludeCategories <span class="string">&#x27;org.gradle.junit.CategoryB&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>TestNG 框架有一个非常相似的概念。在 TestNG 中你可以指定不同的测试组。应从测试执行中 include 或 exclude 的测试组，可以在 test 任务中配置。</p><p><strong>对 TestNG 测试分组</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">test &#123;</span><br><span class="line">    useTestNG &#123;</span><br><span class="line">        excludeGroups <span class="string">&#x27;integrationTests&#x27;</span></span><br><span class="line">        includeGroups <span class="string">&#x27;unitTests&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><h3 id="测试报告"><a href="#测试报告" class="headerlink" title="测试报告"></a>测试报告</h3><p>test 任务默认情况下会生成以下结果。</p><ul><li>一个 HTML 测试报告。</li><li>与 Ant Junit report 任务兼容的 XML 格式的结果。这种格式可以被许多工具所支持，比如CI服务器。</li><li>有效二进制格式的结果。这个任务会从这些二进制结果生成其他的结果。</li></ul><p>您可以使用 Test.setTestReport()方法来禁用 HTML 测试报告。目前不能禁用其他的结果。</p><p>这里还有一个独立的 TestReport 任务类型，它可以从一个或多个 Test 任务实例生成的二进制结果中生成 HTML 测试报告。要使用这个任务类型，你需要定义一个 destinationDir 和要包含到报告的测试结果。这里是一个范例，从子项目的单元测试中生成一个联合报告：</p><p><strong>为多个子项目创建一个单元测试报告</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">subprojects</span> &#123;</span><br><span class="line">    apply plugin: <span class="string">&#x27;java&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Disable the test report for the individual test task</span></span><br><span class="line">    test &#123;</span><br><span class="line">        reports.html.enabled = <span class="keyword">false</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">task</span> testReport(type: TestReport) &#123;</span><br><span class="line">    <span class="keyword">destinationDir</span> = <span class="keyword">file</span>(<span class="string">&quot;$buildDir/reports/allTests&quot;</span>)</span><br><span class="line">    <span class="comment">// Include the results from the `test` task in all subprojects</span></span><br><span class="line">    reportOn <span class="keyword">subprojects</span>*.test</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>你应该注意到，TestReport 类型组合了多个测试任务的结果，并且需要聚合各个测试类的结果。这意味着，如果一个给定的测试类被多个 test 任务所执行，那么测试报告将包括那个类的所有执行结果，但它难以区分那个类的每次执行和它们的输出。</p><h3 id="TestNG-参数化方法和报告"><a href="#TestNG-参数化方法和报告" class="headerlink" title="TestNG 参数化方法和报告"></a>TestNG 参数化方法和报告</h3><p>TestNG 支持参数化测试方法，允许一个特定的测试方法使用不同的输入执行多次。Gradle 会在这个方法的执行报告中包含进它的参数值。</p><p>给定一个带有两个参数，名为 aParameterizedTestMethod 参数化测试方法，它将使用名称这个名称进行报告 ：aParameterizedTestMethod(toStringValueOfParam1, toStringValueOfParam2)。这使得在特定的迭代过程，很容易确定参数值。</p><h3 id="常规值"><a href="#常规值" class="headerlink" title="常规值"></a>常规值</h3><p>表 Java 插件 – test 属性</p><table><thead><tr><th>任务属性</th><th>类型</th><th>默认值</th></tr></thead><tbody><tr><td><code>testClassesDir</code></td><td><code>File</code></td><td><code>sourceSets.test.output.classesDir</code></td></tr><tr><td><code>classpath</code></td><td>FileCollection</td><td><code>sourceSets.test.runtimeClasspath</code></td></tr><tr><td><code>testResultsDir</code></td><td><code>File</code></td><td><code>testResultsDir</code></td></tr><tr><td><code>testReportDir</code></td><td><code>File</code></td><td><code>testReportDir</code></td></tr><tr><td><code>testSrcDirs</code></td><td><code>List</code></td><td><code>sourceSets.test.java.srcDirs</code></td></tr></tbody></table><h2 id="Jar"><a href="#Jar" class="headerlink" title="Jar"></a>Jar</h2><p>Jar 任务创建一个包含类文件和项目资源的 JAR 文件。JAR 文件在 archives 依赖配置中被声明为一个构件。这意味着这个 JAR 文件被包含在一个依赖它的项目的类路径中。如果你把你的项目上传到仓库，这个 JAR 文件会被声明为依赖描述符的一部分。你可以在第16.8节，“创建档案”和第51章， 发布 artifact 中了解如何使用 archives 和配置 artifact。</p><h3 id="Manifest"><a href="#Manifest" class="headerlink" title="Manifest"></a>Manifest</h3><p>每个 jar 或 war 对象都有一个单独的 Manifest 实例的 manifest 属性。当生成 archive 时，相应的 MANIFEST.MF 文件也会被写入进去。</p><p><strong>自定义的 MANIFEST.MF</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">jar &#123;</span><br><span class="line">    manifest &#123;</span><br><span class="line">        attributes(<span class="string">&quot;Implementation-Title&quot;</span>: <span class="string">&quot;Gradle&quot;</span>, <span class="string">&quot;Implementation-Version&quot;</span>: version)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>您可以创建一个单独的 Manifest 实例。它可以用于共享两个 jar 包的 manifest 信息。</p><p><strong>创建一个 manifest 对象。</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ext.sharedManifest = manifest &#123;</span><br><span class="line">    attributes(<span class="string">&quot;Implementation-Title&quot;</span>: <span class="string">&quot;Gradle&quot;</span>, <span class="string">&quot;Implementation-Version&quot;</span>: version)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">task</span> fooJar(type: Jar) &#123;</span><br><span class="line">    manifest = <span class="keyword">project</span>.manifest &#123;</span><br><span class="line">        <span class="keyword">from</span> sharedManifest</span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>你可以把其他的 manifest 合并到任何一个 Manifest 对象中。其他的 manifest 可能使用文件路径来描述，像上面的例子，使用对另一个 Manifest 对象的引用。</p><p><strong>指定 archive 的单独 MANIFEST.MF</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">task</span> barJar(type: Jar) &#123;</span><br><span class="line">    manifest &#123;</span><br><span class="line">        attributes key1: <span class="string">&#x27;value1&#x27;</span></span><br><span class="line">        <span class="keyword">from</span> sharedManifest, <span class="string">&#x27;src/config/basemanifest.txt&#x27;</span></span><br><span class="line">        <span class="keyword">from</span>(<span class="string">&#x27;src/config/javabasemanifest.txt&#x27;</span>, <span class="string">&#x27;src/config/libbasemanifest.txt&#x27;</span>) &#123;</span><br><span class="line">            eachEntry &#123; details -&gt;</span><br><span class="line">                <span class="keyword">if</span> (details.baseValue != details.mergeValue) &#123;</span><br><span class="line">                    details.value = baseValue</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (details.key == <span class="string">&#x27;foo&#x27;</span>) &#123;</span><br><span class="line">                    details.<span class="keyword">exclude</span>()</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;  </span><br></pre></td></tr></table></figure><p>Manifest 会根据在 from 语句中所声明的顺序进行合并。如果基本的 manifest 和要合并的 manifest 都定义了同一个 key 的值，那么默认情况下会采用要合并的 manifest 的值。你可以通过添加 eachEntry action 来完全自定义合并行为，它可以让你对每一项生成的 manifest 访问它的一个 ManifestMergeDetails 实例。这个合并操作不会在 from 语句中就马上被触发。它是懒执行的，不管是对于生成一个 jar 包，还是调用了 writeTo 或者 effectiveManifest</p><p>你可以很轻松地把一个 manifest 写入磁盘中。</p><p><strong>指定 archive 的单独 MANIFEST.MF</strong></p><p><strong>build.gradle</strong></p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jar.manifest.writeTo(<span class="string">&quot;$buildDir/mymanifest.mf&quot;</span>)  </span><br></pre></td></tr></table></figure></article><div class="post-copyright"><div class="copyright-cc-box"><i class="anzhiyufont anzhiyu-icon-copyright"></i></div><div class="post-copyright__author_box"><a class="post-copyright__author_img" href="/" title="头像"><img class="post-copyright__author_img_back" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" title="头像" alt="头像"><img class="post-copyright__author_img_front" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" title="头像" alt="头像"></a><div class="post-copyright__author_name">云少</div><div class="post-copyright__author_desc">站在巨人的肩膀罢了</div></div><div class="post-copyright__post__info"><a class="post-copyright__original" title="该文章为原创文章，注意版权协议" href="https://it985.github.io/posts/e35ffad1.html">原创</a><a class="post-copyright-title"><span onclick='rm.copyPageUrl("https://it985.github.io/posts/e35ffad1.html")'>二十二、Gradle Java 插件</span></a></div><div class="post-tools" id="post-tools"><div class="post-tools-left"><div class="rewardLeftButton"><div class="post-reward" onclick="anzhiyu.addRewardMask()"><div class="reward-button button--animated" title="赞赏作者"><i class="anzhiyufont anzhiyu-icon-hand-heart-fill"></i>打赏作者</div><div class="reward-main"><div class="reward-all"><span class="reward-title">感谢你赐予我前进的力量</span><ul class="reward-group"><li class="reward-item"><a href="/img/wxpay.webp" target="_blank"><img class="post-qr-code-img" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/wxpay.webp" alt="wechat"></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/img/alipay.webp" target="_blank"><img class="post-qr-code-img" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/alipay.webp" alt="alipay"></a><div class="post-qr-code-desc">alipay</div></li></ul><a class="reward-main-btn" href="/about/#about-reward" target="_blank"><div class="reward-text">赞赏者名单</div><div class="reward-dec">因为你们的支持让我意识到写文章的价值🙏</div></a></div></div></div><div id="quit-box" onclick="anzhiyu.removeRewardMask()" style="display:none"></div></div><div class="shareRight"><div class="share-link mobile"><div class="share-qrcode"><div class="share-button" title="使用手机访问这篇文章"><i class="anzhiyufont anzhiyu-icon-qrcode"></i></div><div class="share-main"><div class="share-main-all"><div id="qrcode" title="https://it985.github.io/posts/e35ffad1.html"></div><div class="reward-dec">使用手机访问这篇文章</div></div></div></div></div><div class="share-link weibo"><a class="share-button" target="_blank" href="https://service.weibo.com/share/share.php?title=二十二、Gradle Java 插件&amp;url=https://it985.github.io/posts/e35ffad1.html&amp;pic=https://www.bing.com/th?id=OHR.DarkSkyAcadia_EN-US6966527964_UHD.jpg" rel="external nofollow noreferrer noopener"><i class="anzhiyufont anzhiyu-icon-weibo"></i></a></div><div class="share-link copyurl"><div class="share-button" id="post-share-url" title="复制链接" onclick="rm.copyPageUrl()"><i class="anzhiyufont anzhiyu-icon-link"></i></div></div></div></div></div><div class="post-copyright__notice"><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://it985.github.io" target="_blank">云少IT</a>！</span></div></div><div class="post-tools-right"><div class="tag_share"><div class="post-meta__box"><div class="post-meta__box__tag-list"></div></div><div class="post_share"><div class="social-share" data-image="https://img02.anheyu.com/adminuploads/1/2022/09/05/6315e146a8bbd.webp" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.cbd.int/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload='this.media="all"'><script src="https://cdn.cbd.int/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/5531a826.html"><img class="prev-cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://www.bing.com/th?id=OHR.YellowstoneUGB_EN-US7573964019_UHD.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">二十一、Gradle 标准的 Gradle 插件</div></div></a></div><div class="next-post pull-right"><a href="/posts/a464195b.html"><img class="next-cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://www.bing.com/th?id=OHR.LastDollarRoad_EN-US7923638318_UHD.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">二十三、Gradle Groovy 插件</div></div></a></div></nav><hr><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="anzhiyufont anzhiyu-icon-comments"></i><span> 评论</span></div><div class="comment-randomInfo"><a onclick="anzhiyu.addRandomCommentInfo()" href="javascript:void(0)" rel="external nofollow noreferrer">匿名评论</a><a href="/privacy" style="margin-left:4px">隐私政策</a></div><div class="comment-switch"><span class="first-comment">Twikoo</span><span id="switch-btn"></span><span class="second-comment">Artalk</span></div><div class="comment-tips" id="comment-tips"><span>✅ 你无需删除空行，直接评论以获取最佳展示效果</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div><div><div id="artalk-wrap"></div></div></div></div><div class="comment-barrage"></div></div><div class="aside-content" id="aside-content"><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-bars"></i><span>文章目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%8C%E5%8D%81%E4%BA%8C%E3%80%81Gradle-Java-%E6%8F%92%E4%BB%B6"><span class="toc-number">1.</span> <span class="toc-text">二十二、Gradle Java 插件</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%94%A8%E6%B3%95"><span class="toc-number">1.1.</span> <span class="toc-text">用法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%BA%90%E9%9B%86"><span class="toc-number">1.2.</span> <span class="toc-text">源集</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%BB%E5%8A%A1"><span class="toc-number">1.3.</span> <span class="toc-text">任务</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E5%B8%83%E5%B1%80"><span class="toc-number">1.4.</span> <span class="toc-text">项目布局</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%9B%B4%E6%94%B9%E9%A1%B9%E7%9B%AE%E5%B8%83%E5%B1%80"><span class="toc-number">1.5.</span> <span class="toc-text">更改项目布局</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86"><span class="toc-number">1.6.</span> <span class="toc-text">依赖管理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B8%B8%E8%A7%84%E5%B1%9E%E6%80%A7"><span class="toc-number">1.7.</span> <span class="toc-text">常规属性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%BA%90%E9%9B%86"><span class="toc-number">1.8.</span> <span class="toc-text">使用源集</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%BA%90%E9%9B%86%E5%B1%9E%E6%80%A7"><span class="toc-number">1.9.</span> <span class="toc-text">源集属性</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89%E6%96%B0%E7%9A%84%E6%BA%90%E9%9B%86"><span class="toc-number">1.9.1.</span> <span class="toc-text">定义新的源集</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E4%BA%9B%E6%BA%90%E9%9B%86%E7%9A%84%E8%8C%83%E4%BE%8B"><span class="toc-number">1.10.</span> <span class="toc-text">一些源集的范例</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Javadoc"><span class="toc-number">1.11.</span> <span class="toc-text">Javadoc</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B8%85%E7%90%86"><span class="toc-number">1.12.</span> <span class="toc-text">清理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B5%84%E6%BA%90"><span class="toc-number">1.13.</span> <span class="toc-text">资源</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#CompileJava"><span class="toc-number">1.14.</span> <span class="toc-text">CompileJava</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Test"><span class="toc-number">1.15.</span> <span class="toc-text">Test</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E6%89%A7%E8%A1%8C"><span class="toc-number">1.15.1.</span> <span class="toc-text">测试执行</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%B0%83%E8%AF%95"><span class="toc-number">1.15.2.</span> <span class="toc-text">调试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E8%BF%87%E6%BB%A4"><span class="toc-number">1.15.3.</span> <span class="toc-text">测试过滤</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%80%9A%E8%BF%87%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7%E6%89%A7%E8%A1%8C%E5%8D%95%E4%B8%80%E7%9A%84%E6%B5%8B%E8%AF%95"><span class="toc-number">1.15.4.</span> <span class="toc-text">通过系统属性执行单一的测试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E6%A3%80%E6%B5%8B"><span class="toc-number">1.15.5.</span> <span class="toc-text">测试检测</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E5%88%86%E7%BB%84"><span class="toc-number">1.15.6.</span> <span class="toc-text">测试分组</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E6%8A%A5%E5%91%8A"><span class="toc-number">1.15.7.</span> <span class="toc-text">测试报告</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#TestNG-%E5%8F%82%E6%95%B0%E5%8C%96%E6%96%B9%E6%B3%95%E5%92%8C%E6%8A%A5%E5%91%8A"><span class="toc-number">1.15.8.</span> <span class="toc-text">TestNG 参数化方法和报告</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B8%B8%E8%A7%84%E5%80%BC"><span class="toc-number">1.15.9.</span> <span class="toc-text">常规值</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Jar"><span class="toc-number">1.16.</span> <span class="toc-text">Jar</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Manifest"><span class="toc-number">1.16.1.</span> <span class="toc-text">Manifest</span></a></li></ol></li></ol></li></ol></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div id="footer_deal"><a class="deal_link" href="mailto:2071916845@qq.com" rel="external nofollow noreferrer" title="email"><i class="anzhiyufont anzhiyu-icon-envelope"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://weibo.com/" title="微博"><i class="anzhiyufont anzhiyu-icon-weibo"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.facebook.com/" title="facebook"><i class="anzhiyufont anzhiyu-icon-facebook1"></i></a><a class="deal_link" href="/atom.xml" title="RSS"><i class="anzhiyufont anzhiyu-icon-rss"></i></a><img class="footer_mini_logo" title="返回顶部" alt="返回顶部" onclick="anzhiyu.scrollToDest(0,500)" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" size="50px"><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/it985" title="Github"><i class="anzhiyufont anzhiyu-icon-github"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://space.bilibili.com/300767383" title="Bilibili"><i class="anzhiyufont anzhiyu-icon-bilibili"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://v.douyin.com/" title="抖音"><i class="anzhiyufont anzhiyu-icon-tiktok"></i></a><a class="deal_link" href="/copyright" title="CC"><i class="anzhiyufont anzhiyu-icon-copyright-line"></i></a></div><div id="anzhiyu-footer"><div class="footer-group"><div class="footer-title">服务</div><div class="footer-links"><a class="footer-item" title="51la统计" target="_blank" rel="noopener external nofollow noreferrer" href="https://v6.51.la/">51la统计</a><a class="footer-item" title="十年之约" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.foreverblog.cn/">十年之约</a><a class="footer-item" title="开往" target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/travellings-link/travellings">开往</a></div></div><div class="footer-group"><div class="footer-title">导航</div><div class="footer-links"><a class="footer-item" title="即刻短文" href="/essay/">即刻短文</a><a class="footer-item" title="友链文章" href="/fcircle/">友链文章</a><a class="footer-item" title="留言板" href="/comments/">留言板</a></div></div><div class="footer-group"><div class="footer-title">协议</div><div class="footer-links"><a class="footer-item" title="免责声明" href="/disclaimer/">免责声明</a><a class="footer-item" title="隐私协议" href="/privacy/">隐私协议</a><a class="footer-item" title="Cookies" href="/cookies/">Cookies</a><a class="footer-item" title="版权协议" href="/copyright/">版权协议</a></div></div><div class="footer-group"><div class="footer-title">娱乐</div><div class="footer-links"><a class="footer-item" title="小空调" href="/air-conditioner/">小空调</a><a class="footer-item" title="围住小猫" href="/catch-cat/">围住小猫</a><a class="footer-item" title="免费图床" href="/huluxiapicture/">免费图床</a></div></div><div class="footer-group"><div class="footer-title">推荐分类</div><div class="footer-links"><a class="footer-item" title="Java" href="/categories/Java/">Java</a><a class="footer-item" title="面试" href="/categories/%E9%9D%A2%E8%AF%95/">面试</a></div></div><div class="footer-group"><div class="footer-title-group"><div class="footer-title">友链</div><a class="random-friends-btn" id="footer-random-friends-btn" href="javascript:addFriendLinksInFooter();" rel="external nofollow noreferrer" title="换一批友情链接"><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right"></i></a></div><div class="footer-links" id="friend-links-in-footer"></div></div></div><div id="workboard"><img class="workSituationImg boardsign" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.0.4/img/badge/安知鱼-上班摸鱼中.svg" alt="距离月入25k也就还差一个大佬带我~" title="距离月入25k也就还差一个大佬带我~"><div id="runtimeTextTip"></div></div><div class="wordcount"></div><span>云少已经写了 996.7k 字，</span><span>好像写完一本我国著名的 四大名著 了！！！</span><p id="ghbdages"><a class="github-badge" target="_blank" href="https://hexo.io/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="博客框架为Hexo_v5.4.0" title="博客框架为Hexo_v5.4.0"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.1.5/img/badge/Frame-Hexo.svg" alt="博客框架为Hexo_v5.4.0"></a><a class="github-badge" target="_blank" href="https://www.upyun.com/?utm_source=lianmeng&amp;utm_medium=referral" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站使用又拍云为静态资源提供CDN加速" title="本站使用又拍云为静态资源提供CDN加速"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://img.shields.io/badge/CDN-%E5%8F%88%E6%8B%8D%E4%BA%91-orange%3Fstyle%3Dflat%26logo%3D%E5%8F%88%E6%8B%8D%E4%BA%91" alt="本站使用又拍云为静态资源提供CDN加速"></a><a class="github-badge" target="_blank" href="https://github.com/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站项目由Github托管" title="本站项目由Github托管"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.1.5/img/badge/Source-Github.svg" alt="本站项目由Github托管"></a><a class="github-badge" target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.2.0/img/badge/Copyright-BY-NC-SA.svg" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"></a><a class="github-badge" target="_blank" href="https://icp.gov.moe/?keyword=20221607" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="萌ICP备20221607号" title="萌ICP备20221607号"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://img.shields.io/badge/%E8%90%8CICP%E5%A4%87-20221607-fe1384?style-flat&amp;logo=" alt="萌ICP备20221607号"></a></p></div><div id="footer-bar"><div class="footer-bar-links"><div class="footer-bar-left"><div id="footer-bar-tips"><div class="copyright">&copy;2018 - 2023 By <a class="footer-bar-link" href="/" title="云少" target="_blank">云少</a></div></div><div id="footer-type-tips"></div><div class="js-pjax"><script>function subtitleType(){fetch("https://v1.hitokoto.cn").then(t=>t.json()).then(t=>{var e="出自 "+t.from,p=[];p.unshift(t.hitokoto,e),window.typed=new Typed("#footer-type-tips",{strings:p,startDelay:300,typeSpeed:150,loop:!0,backSpeed:50})})}"function"==typeof Typed?subtitleType():getScript("https://cdn.cbd.int/typed.js@2.0.15/dist/typed.umd.js").then(subtitleType)</script></div></div><div class="footer-bar-right"><a class="footer-bar-link" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="云少">云少</a><a class="footer-bar-link" target="_blank" rel="noopener external nofollow noreferrer" href="https://beian.miit.gov.cn/" title="鄂ICP备2021021095号-2">鄂ICP备2021021095号-2</a><a class="footer-bar-link cc" href="/copyright" title="cc协议"><i class="anzhiyufont anzhiyu-icon-copyright-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-by-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-nc-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-nd-line"></i></a></div></div></div></footer></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="sidebar-site-data site-data is-center"><a href="/archives/" title="archive"><div class="headline">文章</div><div class="length-num">861</div></a><a href="/tags/" title="tag"><div class="headline">标签</div><div class="length-num">35</div></a><a href="/categories/" title="category"><div class="headline">分类</div><div class="length-num">6</div></a></div><span class="sidebar-menu-item-title">功能</span><div class="sidebar-menu-item"><a class="darkmode_switchbutton menu-child" href="javascript:void(0);" rel="external nofollow noreferrer" title="显示模式"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i><span>显示模式</span></a></div><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">网页</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top/" title="博客"><img class="back-menu-item-icon" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/favicon.ico" alt="博客"><span class="back-menu-item-text">博客</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="图床"><img class="back-menu-item-icon" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://www.tryrun.top/favicon.ico" alt="图床"><span class="back-menu-item-text">图床</span></a></div></div></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>望四方</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="anzhiyufont anzhiyu-icon-box-archive faa-tada" style="font-size:.9em"></i><span> 归名档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="anzhiyufont anzhiyu-icon-shapes faa-tada" style="font-size:.9em"></i><span> 归四类</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags faa-tada" style="font-size:.9em"></i><span> 书中签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/charts/"><i class="fa-fw fas fa-chart-bar faa-tada"></i><span> 统计</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="anzhiyufont anzhiyu-icon-link faa-tada" style="font-size:.9em"></i><span> 四方好友</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="anzhiyufont anzhiyu-icon-artstation faa-tada" style="font-size:.9em"></i><span> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><i class="anzhiyufont anzhiyu-icon-envelope faa-tada" style="font-size:.9em"></i><span> 留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/"><i class="anzhiyufont anzhiyu-icon-bilibili faa-tada" style="font-size:.9em"></i><span> 追番页</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/album/"><i class="anzhiyufont anzhiyu-icon-images faa-tada" style="font-size:.9em"></i><span> 刹那间</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/equipment/"><i class="fas fa-heart faa-tada"></i><span> 我的装备</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/collect/"><i class="fas fa-camcorder faa-tada"></i><span> 观影阁</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="anzhiyufont anzhiyu-icon-paper-plane faa-tada" style="font-size:.9em"></i><span> 关于本人</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="anzhiyufont anzhiyu-icon-lightbulb faa-tada" style="font-size:.9em"></i><span> 闲言碎语</span></a></li><li><a class="site-page child faa-parent animated-hover" href="javascript:toRandomPost()" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-shoe-prints1 faa-tada" style="font-size:.9em"></i><span> 随便逛逛</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/disclaimer/"><i class="fas fa-heart faa-tada"></i><span> 免责声明</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/love/"><i class="anzhiyufont anzhiyu-icon-heartbeat faa-tada" style="font-size:.9em"></i><span> 恋爱小屋</span></a></li></ul></div></div><span class="sidebar-menu-item-title">标签</span><div class="card-tags"><div class="item-headline"></div><div class="card-tag-cloud"><a href="/tags/API/" style="font-size:.88rem;color:#758692">API<sup>43</sup></a><a href="/tags/Base64/" style="font-size:.88rem;color:#2584bf">Base64<sup>1</sup></a><a href="/tags/Collectors/" style="font-size:.88rem;color:#bfad3e">Collectors<sup>3</sup></a><a href="/tags/Date/" style="font-size:.88rem;color:#b9b609">Date<sup>3</sup></a><a href="/tags/Executor/" style="font-size:.88rem;color:#14c83c">Executor<sup>9</sup></a><a href="/tags/Guava/" style="font-size:.88rem;color:#0a1878">Guava<sup>1</sup></a><a href="/tags/JVM/" style="font-size:.88rem;color:#625421">JVM<sup>8</sup></a><a href="/tags/Java8/" style="font-size:.88rem;color:#aa71bf">Java8<sup>21</sup></a><a href="/tags/Java9/" style="font-size:.88rem;color:#ad8774">Java9<sup>21</sup></a><a href="/tags/Java%E5%B9%B6%E5%8F%91/" style="font-size:.88rem;color:#19704c">Java并发<sup>20</sup></a><a href="/tags/Lambda/" style="font-size:.88rem;color:#7e5c78">Lambda<sup>4</sup></a><a href="/tags/Lock/" style="font-size:.88rem;color:#700769">Lock<sup>1</sup></a><a href="/tags/Maven/" style="font-size:.88rem;color:#2b8671">Maven<sup>1</sup></a><a href="/tags/Memcached/" style="font-size:.88rem;color:#1b0694">Memcached<sup>23</sup></a><a href="/tags/Mongodb/" style="font-size:.88rem;color:#36202d">Mongodb<sup>49</sup></a><a href="/tags/Queue/" style="font-size:.88rem;color:#643f76">Queue<sup>1</sup></a><a href="/tags/Redis/" style="font-size:.88rem;color:#1e4c38">Redis<sup>27</sup></a><a href="/tags/Stream/" style="font-size:.88rem;color:#a5a097">Stream<sup>4</sup></a><a href="/tags/Thread/" style="font-size:.88rem;color:#05682d">Thread<sup>7</sup></a><a href="/tags/Thread-pool/" style="font-size:.88rem;color:#38ad2a">Thread pool<sup>7</sup></a><a href="/tags/forkJoinPool/" style="font-size:.88rem;color:#827a6b">forkJoinPool<sup>2</sup></a><a href="/tags/stream/" style="font-size:.88rem;color:#4a3ac7">stream<sup>1</sup></a><a href="/tags/%E4%B8%93%E6%A0%8F/" style="font-size:.88rem;color:#b89c14">专栏<sup>35</sup></a><a href="/tags/%E4%BA%8B%E5%8A%A1/" style="font-size:.88rem;color:#922401">事务<sup>1</sup></a><a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size:.88rem;color:#437d09">优化<sup>1</sup></a><a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size:.88rem;color:#705b06">命令<sup>57</sup></a><a href="/tags/%E5%AE%89%E8%A3%85/" style="font-size:.88rem;color:#06a544">安装<sup>6</sup></a><a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size:.88rem;color:#c86c4f">工具<sup>2</sup></a><a href="/tags/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" style="font-size:.88rem;color:#560b2c">数据类型<sup>8</sup></a><a href="/tags/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/" style="font-size:.88rem;color:#4e0a32">生命周期<sup>1</sup></a><a href="/tags/%E7%AE%80%E4%BB%8B/" style="font-size:.88rem;color:#230f8e">简介<sup>7</sup></a><a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size:.88rem;color:#c0771e">算法<sup>10</sup></a><a href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size:.88rem;color:#b40caa">设计模式<sup>38</sup></a><a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size:.88rem;color:#67389a">配置<sup>2</sup></a><a href="/tags/%E9%9D%A2%E8%AF%95/" style="font-size:.88rem;color:#57425c">面试<sup>11</sup></a></div></div><hr></div></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="anzhiyufont anzhiyu-icon-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="anzhiyufont anzhiyu-icon-arrows-left-right"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="anzhiyufont anzhiyu-icon-gear"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="anzhiyufont anzhiyu-icon-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="anzhiyufont anzhiyu-icon-comments"></i></a><button type="button" title="切换背景" onclick="toggleWinbox()"><i class="fas fa-display"></i></button><button id="go-up" type="button" title="回到顶部"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i></button></div></div><div id="algolia-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><button class="search-close-button"><i class="anzhiyufont anzhiyu-icon-xmark"></i></button></nav><div class="search-wrap"><div id="algolia-search-input"></div><hr><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-info"><div class="algolia-stats"></div><div class="algolia-poweredBy"></div></div></div></div></div><div id="search-mask"></div></div><div id="rightMenu"><div class="rightMenu-group rightMenu-small"><div class="rightMenu-item" id="menu-backward"><i class="anzhiyufont anzhiyu-icon-arrow-left"></i></div><div class="rightMenu-item" id="menu-forward"><i class="anzhiyufont anzhiyu-icon-arrow-right"></i></div><div class="rightMenu-item" id="menu-refresh"><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right" style="font-size:1rem"></i></div><div class="rightMenu-item" id="menu-top"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i></div></div><div class="rightMenu-group rightMenu-line rightMenuPlugin"><div class="rightMenu-item" id="menu-copytext"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制选中文本</span></div><div class="rightMenu-item" id="menu-pastetext"><i class="anzhiyufont anzhiyu-icon-paste"></i><span>粘贴文本</span></div><a class="rightMenu-item" id="menu-commenttext"><i class="anzhiyufont anzhiyu-icon-comment-medical"></i><span>引用到评论</span></a><div class="rightMenu-item" id="menu-newwindow"><i class="anzhiyufont anzhiyu-icon-window-restore"></i><span>新窗口打开</span></div><div class="rightMenu-item" id="menu-copylink"><i class="anzhiyufont anzhiyu-icon-link"></i><span>复制链接地址</span></div><div class="rightMenu-item" id="menu-copyimg"><i class="anzhiyufont anzhiyu-icon-images"></i><span>复制此图片</span></div><div class="rightMenu-item" id="menu-downloadimg"><i class="anzhiyufont anzhiyu-icon-download"></i><span>下载此图片</span></div><div class="rightMenu-item" id="menu-newwindowimg"><i class="anzhiyufont anzhiyu-icon-window-restore"></i><span>新窗口打开图片</span></div><div class="rightMenu-item" id="menu-search"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span>站内搜索</span></div><div class="rightMenu-item" id="menu-searchBaidu"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span>百度搜索</span></div><div class="rightMenu-item" id="menu-music-toggle"><i class="anzhiyufont anzhiyu-icon-play"></i><span>播放音乐</span></div><div class="rightMenu-item" id="menu-music-back"><i class="anzhiyufont anzhiyu-icon-backward"></i><span>切换到上一首</span></div><div class="rightMenu-item" id="menu-music-forward"><i class="anzhiyufont anzhiyu-icon-forward"></i><span>切换到下一首</span></div><div class="rightMenu-item" id="menu-music-playlist" onclick="window.open(&quot;https://y.qq.com/n/ryqq/playlist/8802438608&quot;, &quot;_blank&quot;);" style="display:none"><i class="anzhiyufont anzhiyu-icon-radio"></i><span>查看所有歌曲</span></div><div class="rightMenu-item" id="menu-music-copyMusicName"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制歌名</span></div></div><div class="rightMenu-group rightMenu-line rightMenuOther"><a class="rightMenu-item menu-link" id="menu-randomPost"><i class="anzhiyufont anzhiyu-icon-shuffle"></i><span>随便逛逛</span></a><a class="rightMenu-item menu-link" href="/categories/"><i class="anzhiyufont anzhiyu-icon-cube"></i><span>博客分类</span></a><a class="rightMenu-item menu-link" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags"></i><span>文章标签</span></a></div><div class="rightMenu-group rightMenu-line rightMenuOther"><a class="rightMenu-item" id="menu-copy" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制地址</span></a><a class="rightMenu-item" id="menu-commentBarrage" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-message"></i><span class="menu-commentBarrage-text">关闭热评</span></a><a class="rightMenu-item" id="menu-darkmode" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i><span class="menu-darkmode-text">深色模式</span></a><a class="rightMenu-item" id="menu-translate" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-language"></i><span>轉為繁體</span></a></div></div><div id="rightmenu-mask"></div><div id="he-plugin-simple"></div><script>var WIDGET={CONFIG:{modules:"0124",background:"2",tmpColor:"FFFFFF",tmpSize:"16",cityColor:"FFFFFF",citySize:"16",aqiColor:"E8D87B",aqiSize:"16",weatherIconSize:"24",alertIconSize:"18",padding:"10px 10px 10px 10px",shadow:"0",language:"auto",borderRadius:"20",fixed:"true",vertical:"top",horizontal:"left",left:"20",top:"7.1",key:"df245676fb434a0691ead1c63341cd94"}}</script><link rel="stylesheet" href="https://widget.qweather.net/simple/static/css/he-simple.css?v=1.4.0"><script src="https://widget.qweather.net/simple/static/js/he-simple.js?v=1.4.0"></script><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.cbd.int/@fancyapps/ui@5.0.20/dist/fancybox/fancybox.umd.js"></script><script src="https://cdn.cbd.int/instant.page@5.2.0/instantpage.js" type="module"></script><script src="https://cdn.cbd.int/vanilla-lazyload@17.8.4/dist/lazyload.iife.min.js"></script><script src="https://cdn.cbd.int/node-snackbar@0.1.16/dist/snackbar.min.js"></script><script>function panguFn(){"object"==typeof pangu?pangu.autoSpacingPage():getScript("https://cdn.cbd.int/pangu@4.0.7/dist/browser/pangu.min.js").then(()=>{pangu.autoSpacingPage()})}function panguInit(){panguFn()}document.addEventListener("DOMContentLoaded",panguInit)</script><script>var meting_api="https://api.injahow.cn/meting/?server=:server&type=:type&id=:id&auth=:auth&r=:r"</script><canvas id="universe"></canvas><script async src="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.0/dark/dark.js"></script><script>var HoldLog=console.log;console.log=function(){};let now1=new Date;queueMicrotask(()=>{function o(){HoldLog.apply(console,arguments)}var c=new Date("09/01/2018 00:00:00"),c=(now1.setTime(now1.getTime()+250),(now1-c)/1e3/60/60/24),c=["欢迎使用安知鱼!","生活明朗, 万物可爱",`
        
       █████╗ ███╗   ██╗███████╗██╗  ██╗██╗██╗   ██╗██╗   ██╗
      ██╔══██╗████╗  ██║╚══███╔╝██║  ██║██║╚██╗ ██╔╝██║   ██║
      ███████║██╔██╗ ██║  ███╔╝ ███████║██║ ╚████╔╝ ██║   ██║
      ██╔══██║██║╚██╗██║ ███╔╝  ██╔══██║██║  ╚██╔╝  ██║   ██║
      ██║  ██║██║ ╚████║███████╗██║  ██║██║   ██║   ╚██████╔╝
      ╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝╚═╝   ╚═╝    ╚═════╝
        
        `,"已上线",Math.floor(c),"天","©2018 By 安知鱼 V1.6.6"],e=["NCC2-036","调用前置摄像头拍照成功，识别为【小笨蛋】.","Photo captured: ","🤪"];setTimeout(o.bind(console,`
%c${c[0]} %c ${c[1]} %c ${c[2]} %c${c[3]}%c ${c[4]}%c ${c[5]}

%c ${c[6]}
`,"color:#425AEF","","color:#425AEF","color:#425AEF","","color:#425AEF","")),setTimeout(o.bind(console,`%c ${e[0]} %c ${e[1]} %c 
${e[2]} %c
${e[3]}
`,"color:white; background-color:#4fd953","","",'background:url("https://npm.elemecdn.com/anzhiyu-blog@1.1.6/img/post/common/tinggge.gif") no-repeat;font-size:450%')),setTimeout(o.bind(console,"%c WELCOME %c 你好，小笨蛋.","color:white; background-color:#4f90d9","")),setTimeout(console.warn.bind(console,"%c ⚡ Powered by 安知鱼 %c 你正在访问 云少 的博客.","color:white; background-color:#f0ad4e","")),setTimeout(o.bind(console,"%c W23-12 %c 你已打开控制台.","color:white; background-color:#4f90d9","")),setTimeout(console.warn.bind(console,"%c S013-782 %c 你现在正处于监控中.","color:white; background-color:#d9534f",""))})</script><script async src="/anzhiyu/random.js"></script><script async>!function(){var n,o,r,a,i,e=new Date("09/01/2018 00:00:00"),l=new Date;setInterval(()=>{var t;if(l=new Date,i=l.getHours(),t=(l-e)/1e3/60/60/24,n=Math.floor(t),t=(l-e)/1e3/60/60-24*n,o=Math.floor(t),1==String(o).length&&(o="0"+o),t=(l-e)/1e3/60-1440*n-60*o,r=Math.floor(t),1==String(r).length&&(r="0"+r),t=(l-e)/1e3-86400*n-3600*o-60*r,a=Math.round(t),1==String(a).length&&(a="0"+a),document.getElementById("footer")){let e="";e=(i<18&&9<=i||((t=document.querySelector("#workboard .workSituationImg")).src="https://npm.elemecdn.com/anzhiyu-blog@2.0.4/img/badge/安知鱼-下班啦.svg",t.title="下班了就该开开心心的玩耍，嘿嘿~",t.alt="下班了就该开开心心的玩耍，嘿嘿~"),`本站居然运行了 ${n} 天<span id='runtime'> ${o} 小时 ${r} 分 ${a} 秒 </span><i class='anzhiyufont anzhiyu-icon-heartbeat' style='color:red'></i>`),document.getElementById("runtimeTextTip")&&(document.getElementById("runtimeTextTip").innerHTML=e)}},1e3)}()</script><script src="https://cdn.cbd.int/algoliasearch@4.18.0/dist/algoliasearch-lite.umd.js"></script><script src="https://cdn.cbd.int/instantsearch.js@4.56.5/dist/instantsearch.production.min.js"></script><script src="/js/search/algolia.js"></script><div class="js-pjax"><script>(()=>{const e=document.querySelectorAll("#article-container .mermaid-wrap");if(0!==e.length){const n=()=>{window.loadMermaid=!0;const a="dark"===document.documentElement.getAttribute("data-theme")?"dark":"default";Array.from(e).forEach((e,t)=>{const n=e.firstElementChild;e="%%{init:{ 'theme':'"+a+"'}}%%\n"+n.textContent;const d=mermaid.render("mermaid-"+t,e);"string"==typeof d?(t=d,n.insertAdjacentHTML("afterend",t)):d.then(({svg:e})=>{n.insertAdjacentHTML("afterend",e)})})};var t=()=>{window.loadMermaid?n():getScript("https://cdn.cbd.int/mermaid@10.2.4/dist/mermaid.min.js").then(n)};anzhiyu.addGlobalFn("themeChange",n,"mermaid"),window.pjax?t():document.addEventListener("DOMContentLoaded",t)}})()</script><script>(()=>{const t=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://twikoo.tryrun.top/",region:"",onCommentLoaded:()=>{anzhiyu.loadLightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null))};var o=()=>{"object"==typeof twikoo?setTimeout(n,0):getScript("https://cdn.cbd.int/twikoo@1.6.18/dist/twikoo.all.min.js").then(n)};const n=()=>{t()};anzhiyu.loadComment(document.getElementById("twikoo-wrap"),o)})()</script><script>(()=>{const t=()=>{window.artalkItem=new Artalk(Object.assign({el:"#artalk-wrap",server:"https://artalk.tryrun.top/",site:"https://blog.tryrun.top/",pageKey:location.pathname,darkMode:"dark"===document.documentElement.getAttribute("data-theme"),countEl:".artalk-count"},null)),"null"!==GLOBAL_CONFIG.lightbox&&window.artalkItem.use(t=>{t.on("list-loaded",()=>{t.getCommentList().forEach(t=>{t=t.getRender().$content;anzhiyu.loadLightbox(t.querySelectorAll("img:not([atk-emoticon])"))})})})};var a=async()=>{"object"==typeof window.artalkItem||(await getCSS("https://cdn.cbd.int/artalk@2.5.5/dist/Artalk.css"),await getScript("https://cdn.cbd.int/artalk@2.5.5/dist/Artalk.js")),t()};anzhiyu.addGlobalFn("themeChange",t=>{var a=document.getElementById("artalk-wrap");a&&a.children.length&&window.artalkItem.setDarkMode("dark"===t)},"artalk"),window.loadOtherComment=a})()</script><input type="hidden" name="page-type" id="page-type" value="post"></div><script>window.addEventListener("load",()=>{const t=e=>e=""!==e&&150<(e=(e=(e=(e=e.replace(/<img.*?src="(.*?)"?[^\>]+>/gi,"[图片]")).replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,"[链接]")).replace(/<pre><code>.*?<\/pre>/gi,"[代码]")).replace(/<[^>]+>/g,"")).length?e.substring(0,150)+"...":e,n=t=>{let n="";if(t.length)for(let e=0;e<t.length;e++)n=(n=(n+="<div class='aside-list-item'>")+`<a href='${t[e].url}' class='thumbnail'><img data-lazy-src='${t[e].avatar}' alt='${t[e].nick}'><div class='name'><span>${t[e].nick} </span></div></a>`)+`<div class='content'>
        <a class='comment' href='${t[e].url}' title='${t[e].content}'>${t[e].content}</a>
        <time datetime="${t[e].date}">${anzhiyu.diffDate(t[e].date,!0)}</time></div>
        </div>`;else n+="没有评论";var e=document.querySelector("#card-newest-comments .aside-list");e.innerHTML=n,window.lazyLoadInstance&&window.lazyLoadInstance.update(),window.pjax&&window.pjax.refresh(e)};var e=()=>{var e;document.querySelector("#card-newest-comments .aside-list")&&((e=saveToLocal.get("twikoo-newest-comments"))?n(JSON.parse(e)):(e=()=>{twikoo.getRecentComments({envId:"https://twikoo.tryrun.top/",region:"",pageSize:6,includeReply:!0}).then(function(e){e=e.map(e=>({content:t(e.comment),avatar:e.avatar,nick:e.nick,url:e.url+"#"+e.id,date:new Date(e.created).toISOString()}));saveToLocal.set("twikoo-newest-comments",JSON.stringify(e),10/1440),n(e)}).catch(function(e){document.querySelector("#card-newest-comments .aside-list").textContent="无法获取评论，请确认相关配置是否正确"})},"object"==typeof twikoo?e():getScript("https://cdn.cbd.int/twikoo@1.6.18/dist/twikoo.all.min.js").then(e)))};e(),document.addEventListener("pjax:complete",e)})</script><script async data-pjax src="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.1/bubble/bubble.js"></script><script>var visitorMail="visitor@anheyu.com"</script><script async data-pjax src="https://cdn.cbd.int/anzhiyu-theme-static@1.0.0/waterfall/waterfall.js"></script><script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qrcodejs/1.0.0/qrcode.min.js"></script><script src="/js/anzhiyu/right_click_menu.js"></script><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.1.9/icon/ali_iconfont_css.css"><script async src="/js/1.min.js?1"></script><script async src="/js/bg.js?1"></script><script async src="https://cdn1.tianli0.top/npm/sweetalert2@8.19.0/dist/sweetalert2.all.js"></script><script async src="/js/lunar.min.js?1"></script><script async src="/js/day.min.js?1"></script><script async src="/js/winbox.bundle.min.js?1"></script><script id="click-show-text" src="https://cdn.cbd.int/butterfly-extsrc@1.1.3/dist/click-show-text.min.js" data-mobile="true" data-text="富强,民主,文明,和谐,自由,平等,公正,法治,爱国,敬业,诚信,友善" data-fontsize="15px" data-random="true" async></script><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.0.0/aplayer/APlayer.min.css" media="print" onload='this.media="all"'><script src="https://cdn.cbd.int/anzhiyu-blog-static@1.0.1/js/APlayer.min.js"></script><script src="https://cdn.cbd.int/hexo-anzhiyu-music@1.0.1/assets/js/Meting2.min.js"></script><script src="https://cdn.cbd.int/pjax@0.2.8/pjax.min.js"></script><script>let pjaxSelectors=['meta[property="og:image"]','meta[property="og:title"]','meta[property="og:url"]','meta[property="og:type"]','meta[property="og:site_name"]','meta[property="og:description"]',"head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"];var pjax=new Pjax({elements:'a:not([target="_blank"])',selectors:pjaxSelectors,cacheBust:!1,analytics:!0,scrollRestoration:!1});document.addEventListener("pjax:send",function(){if(anzhiyu.removeGlobalFnEvent("pjax"),anzhiyu.removeGlobalFnEvent("themeChange"),document.getElementById("rightside").classList.remove("rightside-show"),window.aplayers)for(let e=0;e<window.aplayers.length;e++)window.aplayers[e].options.fixed||window.aplayers[e].destroy();"object"==typeof typed&&typed.destroy();var e=document.body.classList;e.contains("read-mode")&&e.remove("read-mode")}),document.addEventListener("pjax:complete",function(){window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach(e=>{const t=document.createElement("script");var a=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach(e=>t.setAttribute(e.name,e.value)),t.appendChild(document.createTextNode(a)),e.parentNode.replaceChild(t,e)}),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update(),"function"==typeof chatBtnFn&&chatBtnFn(),"function"==typeof panguInit&&panguInit(),"function"==typeof gtag&&gtag("config","G-3VMKW5TZBM",{page_path:window.location.pathname}),"object"==typeof _hmt&&_hmt.push(["_trackPageview",window.location.pathname]),"function"==typeof loadMeting&&document.getElementsByClassName("aplayer").length&&loadMeting(),"object"==typeof Prism&&Prism.highlightAll()}),document.addEventListener("pjax:error",e=>{404===e.request.status&&pjax.loadUrl("/404.html")})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><script charset="UTF-8" src="https://cdn.cbd.int/anzhiyu-theme-static@1.1.5/accesskey/accesskey.js"></script></div><div id="popup-window"><div class="popup-window-title">通知</div><div class="popup-window-divider"></div><div class="popup-window-content"><div class="popup-tip">你好呀</div><div class="popup-link"><i class="anzhiyufont anzhiyu-icon-arrow-circle-right"></i></div></div></div></body></html>